As someone relatively new to Angular, I come with some experience from working with other JavaScript frameworks like Vue and React. Currently, I am developing an Angular Lab application that interacts with 2 APIs to retrieve information. After receiving the data, I am attempting to refresh a child component embedded inside the parent (child known as Main and parent called App).
My primary challenge lies in updating the template of this child component, as I am struggling to find helpful resources online.
Here is an overview of my execution flow: The parent component consists of a textbox and a button. When a user enters a city name and clicks the button, the first API is triggered to fetch the coordinates of the specified city. Once this is done, the coordinates are used to call the second API, which returns the weather code for those coordinates. Finally, these weather codes are displayed in the child component.
To manage the button click event, I have implemented a Directive that utilizes a Service for storing values.
PS: I am utilizing Angular 14.
Below is some sample code:
Directive
@Directive({
selector: '<button [showWeather]>'
})
export class ShowWeatherDirective {
constructor(private sharedService: SharingService,
private askApi: ServiceAskAPIService,
private askLocation: ServiceGetCityLocationAPIService,) { }
currentWeather = this.sharedService.weatherResults$;
@HostListener('click',['$event.target'])
onClick(btn: any){
console.log("Button clicked", btn);
this.getCityWeather();
}
getCityWeather(){
var city =(document.getElementById("cityInput") as HTMLInputElement).value;
this.askLocation.getCityLocation(city)
.then(location=>{
this.askApi.getCityWeather(location.toString()).then(answer=>{
// after both apis have answered we process the data
console.log(answer);
console.log(answer.valueOf)
let jsonparsed = JSON.parse(answer);
let myWeeklyIntervals = jsonparsed.data.timelines[0].intervals
const weatherCodes : WeatherCodes[] = [
{
id:0,
weather:"",
img:"",
}
]
for(let res of myWeeklyIntervals){
let weathercode : WeatherCodes = {
id: 0,
weather:"",
img:""
}
console.log(res);
weathercode.id = res.values.weatherCode;
weatherCodes.push(weathercode);
}
console.log(weatherCodes)
this.sharedService.updateWeatherResults(weatherCodes);
})
});
}
}
Sharing service
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class SharingService {
private sharingObject = new Subject<any[]>();
weatherResults$ = this.sharingObject.asObservable();
constructor() { }
get sharingValue() {
return this.sharingObject
}
set sharingValue(obj) {
this.sharingObject = obj;
}
updateWeatherResults(results: any[]){
this.sharingObject.next(results);
}
}
Child component
@Component({
selector: 'component-main',
templateUrl: './main.component.html',
styleUrls: ['./main.component.css']
})
export class MainComponent {
private weatherResults =new BehaviorSubject<Object>(this.sharedService.weatherResults$);
weatherResultObservable$: Observable<Object> = this.weatherResults.asObservable();
weatherCodes: WeatherCodes[] = [
...
];
currentWeather: WeatherCodes[] = [];
constructor(private sharedService: SharingService){}
}
Child component template
<p>main works!</p>
<div id="MyClass" *ngIf="weatherResultObservable$| async">
<p> {{weatherResultObservable$}}</p>
</div>
<script>
console.log("nope")
</script>
I apologize if there are any inaccuracies, as I am still learning. Thank you for your understanding and assistance.
I attempted to utilize Observables for handling live reload functionality, but I seem to be missing something crucial that is causing confusion.