Reputation: 515
I am having two components on one page: parent and child.
Parent component makes a get request getCityForecast(cityCode)
and binds the data to the child component.
The issue is that the child component reders before the parent one. and data is not popelated. How I can solve it?
<div class="search-field">
<input type="search" placeholder="Search..." [(ngModel)]="cityInput" (ngModelChange)="getAutoCompleteResults()">
<button class="search-button">
<svg id="search-icon" class="search-icon" viewBox="0 0 24 24">
<path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>
<path d="M0 0h24v24H0z" fill="none"/>
</svg>
</button>
<div *ngIf="hasSearchResults()">
<p *ngFor="let city of autoCompleteSearchResults" (click)="cityChoice(city.LocalizedName, city.Key); getCityForecast(city.Key)">{{city.LocalizedName}}</p>
</div>
</div>
<app-todays-forecast
[city]="cityDetails"
[todaysForecast]="todaysForecast">
</app-todays-forecast>
import { Component, OnInit } from '@angular/core';
import { DataFetchService } from '../services/data-fetch.service';
import { HttpClient } from '@angular/common/http';
@Component({
selector: 'app-local-forecast',
templateUrl: './local-forecast.component.html',
styleUrls: ['./local-forecast.component.scss']
})
export class LocalForecastComponent implements OnInit {
autoCompleteSearchResults: any;
cityInput: string = '';
cityDetails: any = {};
defaultCityCode = 210841;
defaultCityName: string = 'Tel-Aviv';
todaysForecast: any;
constructor(private fetchData: DataFetchService,
private http: HttpClient) { }
ngOnInit(): void {
this.cityDetails.name = this.defaultCityName;
this.getCityForecast(this.defaultCityCode);
console.log(this.todaysForecast);
}
hasSearchResults() {
return this.autoCompleteSearchResults?.length > 0;
}
cityChoice(name, key) {
this.cityDetails.name = name;
this.cityDetails.key = key;
}
getAutoCompleteResults() {
this.fetchData.fetchAutoCompleteResults(this.cityInput)
.subscribe(
result => { this.autoCompleteSearchResults = result },
err => console.log(`we have an error: ${err}`)
)
}
getCityForecast(cityCode) {
this.fetchData.getCityForecast(cityCode)
.subscribe(
result => this.todaysForecast = result[0],
err => console.log(`we have an error: ${err}`)
);
}
<h1>Today's Weather in {{city.name}}</h1>
<p>Temperature: {{temperature}}°С</p>
<p>Weather: {{conditions}}</p>
import { Component, OnInit, Input } from '@angular/core';
import { DataFetchService } from 'src/app/services/data-fetch.service';
import { HttpClient } from '@angular/common/http';
@Component({
selector: 'app-todays-forecast',
templateUrl: './todays-forecast.component.html',
styleUrls: ['./todays-forecast.component.scss']
})
export class TodaysForecastComponent implements OnInit {
@Input() city: any;
@Input() todaysForecast: any;
temperature: any;
conditions: any;
constructor( public fetchData: DataFetchService) { }
ngOnInit(): void {
console.log('this.todaysForecast >>>', this.todaysForecast);
this.temperature = this.todaysForecast?.Temperature.Metric.Value;
this.conditions = this.todaysForecast?.WeatherText;
}
}
Upvotes: 1
Views: 848
Reputation: 442
If you want to fetch data before your component is rendered you can use an Resolver.
https://angular.io/api/router/Resolve
Upvotes: 1
Reputation: 15230
There are several ways to do it:
*ngIf="data"
where data
is the data retrieved from backendnull
or undefined
values in a specific wayObservable
in child component (usually more complex and does not fit the intelligent/dumb components principles)Upvotes: 1
Reputation: 57971
instead of use ngOnInit, use a "setter" in @Input
@Input() todaysForecast(value){
this.temperature = value.Temperature.Metric.Value;
this.conditions = value.WeatherText;
//is you need it you can also use another variable "_todayForecast
//this._todayForecast=value
}
//and a getter
get todayForecast(){
return this._todayForecast
}
or implements OnChanges
export class TodaysForecastComponent implements OnChanges {
@Input() todaysForecast;
ngOnChanges(changes: SimpleChanges) {
// changes.prop contains the old and the new value...
}
}
Upvotes: 2