Hello, I'm really new in ember, and I tried dive into the documentation, but with all the different versions, and different changes, I didn't really understand how to do it, I have a search box, when I click search, it calls my API which gives me some data, everything is great, but, I don't know how to access it from my view, each time my data is changed ?
I'm using ember-cli 5.5, the latest version, and initialized through the cli, so it's really all the latest versions.
Any help please ?
#How to get data from API and update model/ data shown
1 messages · Page 1 of 1 (latest)
Is the data from the search box being used through the app or just in this component ?
Well i have an api service which communicates with my server
I also created a setter and getter for the data, which i try to access through the app, but i can’t use it/didn’t know how to
Ok give me one second
Alright thank you!
Ok you ready ?
I'm going to go one file at a time
//Add these imports to the top of your service file
import { tracked } from '@glimmer/tracking';
import { A } from '@ember/array';
//Add this code to your search service file
@tracked mySearchData = A([]);
yourSearchRequestFunction(value){
//do your ajax stuff here to get your data
let fetchCall = fetch();
let response = fetchCall.json();
this.mySearchData.clear();
this.mySearchData.addObjects(response)
}
So this goes in your service file.. you probably already have a function that does a fetch to your server correct ?
Exactly, I’m using axios and storing the response inside the getter, give me 5 min i will show you my functions
components/weather-search.js file :
import { service } from '@ember/service';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
export default class WeatherSearchComponent extends Component {
@tracked cityName = '';
@service api;
@action
async getWeatherFromCity() {
try {
const weatherData = await this.api.getWeather(this.cityName);
console.log(weatherData);
return weatherData;
} catch (error) {
if (error.response && error.response.status === 404) {
console.error('City not found:', this.cityName);
} else {
console.error('error fetching weather data:', error);
}
}
}
}
Inside the api service :
import Service, { service } from '@ember/service';
import axios from 'axios';
export default class ApiService extends Service {
@service('weather-data') weatherDataService;
async getWeather(cityName) {
// Lien vers le backend
const apiUrl = `http://localhost:3000/api/forecast/weather?city=${cityName}`;
try {
const response = await axios.get(apiUrl);
this.weatherDataService.setWeatherData(response.data);
console.log(17, this.weatherDataService.getWeatherData());
return response.data;
} catch (error) {
console.error('Error fetching data: ', error);
throw new Error('failed to fetch data');
}
}
}
And the weatherDataService :
import Service from '@ember/service';
import { tracked } from '@glimmer/tracking';
export default class WeatherDataService extends Service {
@tracked weatherData = {};
setWeatherData(data) {
this.weatherData = data.forecast;
console.log('weatherData updated : ', data.forecast);
}
getWeatherData() {
return this.weatherData;
}
}
and one last thing can you post your template file.
{{page-title "WeatherDisplay"}}
<WeatherDisplay @weatherData={{@model}}/>
{{outlet}}
What I would want, is to access data and update it when I search for another city, inside my "weather-display"
So one thing I started to realize in ember. If your template file is using functions to output variables then it will only be called once.. So what that means is .. if you trying to show dynamic data then you need to use @weatherData.someProperty instead of this.showSomePropert()
you want to do this
{{ @weatherData.someProperty }}
instead of this
{{ this.showSomeProperty() }}
inside the template.hbs file of your Weather-dislay component
That's how I'm doing it, inside the weather-display's component
Oh I see why
you should be using the
@weatherData={{this.weatherDataService.weatherData}}
You're not trying to use the model that you return from the function. You're trying to use the data that your setting on the service
yes as long as the Weather service is on the component you can access the the properties that it has
Is it possible to log it, to check if it's working ?
Since it's javascript.. you can use "debugger;" statements in your frontend code
then open the developer tools.. when it hits your code it will stop execution like a break point
you could do console.log(data) but you rather use debugger statements because then you can check a bunch of different things at once
You could also set breakpoints in the developer tools manually but it's annoying looking for files depending on how you have your project setup
Alright ! thank you so much
Alright, the changes are still not taken in consideration, weirdly..
Ok I think you might have some stuff to clean up
WeatherSearch Component calls WeatherDisplay?
nope, they're not related
Weathersearch is only a component and are not really "linked"
Ok Did you make sure that the your API service is getting data ?
you could see that in the network tab of your developer tools
Yes it is correctly getting the data, even when I console log the service getter / setter
Everything work, besides how to show it haha
Yes, because the search will call the api service, to make the api call
And update my weatherData to show the data
Ok let me show you some code on how I would set it up because I think it just might be the way you have it setup
Alright thank you so much !
Ok
Here is all the stuff you need
Two components and one service file
actually 4 files,
component/weatherSearch/component.js
import Component from '@glimmer/component';
import { service } from '@ember/service';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
export default class WeatherSearchComponent extends Component {
@tracked cityName = '';
@service weatherService;
@action
async getWeatherFromCity() {
try {
const weatherData = await this.weatherService.getWeather(this.cityName);
console.log(weatherData);
return weatherData;
} catch (error) {
if (error.response && error.response.status === 404) {
console.error('City not found:', this.cityName);
} else {
console.error('error fetching weather data:', error);
}
}
}
}
component/weatherSearch/template.hbs
<Input type="text" @value={{this.cityName}} />
<div {{on "click" this.getWeatherFromCity }} >GetResults </div>
<WeatherSearchDisplay @data={{this.weatherService.weatherData>
component/weatherSearchDisplay/template.hbs
<ul>
<li>Name: <p>{{@data.name}}</p></li>
<li>Date:<p>{{@data.dt}}</p></li>
<ul>
service/weatherService.js
import Service from '@ember/service';
import { tracked } from '@glimmer/tracking';
import axios from 'axios';
export default class WeatherDataService extends Service {
@tracked weatherData = {};
getWeather(cityName) {
const apiUrl = `http://localhost:3000/api/forecast/weather?city=${cityName}`;
const response = await axios.get(apiUrl);
//make sure your response is an object
return this.weatherData = response;
}
}
Hello, I'm sorry for the late answer, I'm gonna try this right now, and I'll keep you updated !
yeah no problem
Lets gooooooo!!! I'm glad you got it, and you learned something.
Yes thank you so much, but in that case, when should I use router / controller ?
So you use the router.js as your entry file to setup the page. So lets say after your user logins in you send them to the WeatherSearch page... the router.js file can use the beforeModel() to check to make sure user has rights to that page
if they don't then redirect them to login page
or you can use it to preload some data that the user may need in order to search .. like you can get data to preload some options for a select and pass that data to your controller...
Ohh I see !
And , in the architecture you gave me, should I create a file named "route.js" inside for example "weather-search" folder, to use it as a router ?
are you using classic, or pods setup?
Humm, I really don't know haha, didn't get to this point, sorry
no problem
but you really only use route.js files for pages
so lets say you have a /login page
you would have 3 files for that. a template.hbs, route.js, controller.js
route.js is the first file that gets hit.. allows for data setup... controller.js is next... allows you to hold actions that you will use for button clicks, tracked properties for when you want to show dynamica data, and functions to help you render data, also services if you've created any to help you create reusable functionality for your website
template.hbs is rendering file that will render components ..
components will have component.js which is like a controller, but for components only, anything you can do in a controller you can do in a component file... and a template.hbs file ...
no problem.. Happy programming. 
Hello, I'm sorry to bother you once again, but inside the hbs file, how to access, for example to the first index of an array ? let's say {{@data.weather[0].description}} because it's not working that way
No.. only if it's a array/... then you use each...
I recommend creating a getter in your component's .js file that returns the first item in the array, e.g.
get firstResult() {
return this.args.data.weather[0];
}
Then, in your template you can access it:
{{this.firstResult.description}}