Modifying an Angular Component Template following an API Response

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.

Answer №1

It's a bit of a mystery how I managed to solve this problem, but here is the solution that worked for me. I'm sharing it in case it may help someone else facing a similar issue:

I made some changes to my MainComponent (child) so that it subscribes to a service storing data during initialization (ngOnInit()):

export class ChildComponent implements OnInit{

  weatherResultObservable$: Observable<any[]> | undefined;

  currentWeather: WeatherCodes[] = [];

  constructor(private sharedService: SharingService){}

  ngOnInit(): void {
      this.weatherResultObservable$ = this.sharedService.weatherResults$;
      this.weatherResultObservable$.subscribe((results)=>{
        this.currentWeather=results;
      })
  }
}

Following this, I updated the template of my ChildComponent to properly display the object: (Please note that 'weather.weather' refers to an interface that is not included in this example)

<div id="MyClass" *ngIf="weatherResultObservable$ | async">
  <p *ngFor="let weather of currentWeather">{{ weather.weather }}</p>
</div>

Output:

https://i.sstatic.net/FklFg.png

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Angular's forEach function seems to be stuck and not loop

I'm attempting to cycle through a list of objects in my Angular/Typescript code, but it's not working as expected. Here is the code snippet: businessList: RemoteDataSet<BusinessModel>; businessModel: BusinessModel; this.businessList.forE ...

Unraveling the mysteries of an undefined entity

When the variable response is undefined, attempting to retrieve its property status will result in an error: Error: Unable to access property 'status' of undefined const { response, response: { status }, request, config, } = error as A ...

Angular 2: Issue with directive not triggering set function

I am puzzled as to why the alert() function within the setter of my directive is only triggered once when the value of the input element it is applied to changes. It works on the initial page load but not subsequently. I was expecting that since the value ...

Unfortunately, the package "error-ex" could not be found when attempting to access it through the npm registry

I am encountering an issue while trying to install npm package dependencies in my Angular application. The error message I receive is related to "error-ex@^1.2.0". Can anyone provide guidance on how to resolve this problem? npm ERR! code E404 npm ERR! 404 ...

Angular's ExpressionChangedAfterItHasBeenCheckedError is a common issue that developers encounter

This message continues the discussion about a persistent issue I have been facing. Here is the link to the original thread on Stack Overflow: stackoverflow.com/questions/44596418/angular-throws-expressionchangedafterithasbeencheckederror-with-textarea Af ...

Identifying modifications within the @Input property in Angular 4

Can someone clarify how to detect changes in an @Input property within a component, rather than just when passed from its parent? I haven't found a clear answer to this yet. Thank you! ...

Just updated to Angular 10, encountered issue: Unable to modify the read-only property 'listName' of an object

After updating my Angular project from version 8 to version 10, I encountered an error while trying to edit an input field in a Material Dialog. The error message displayed is as follows: ERROR TypeError: Cannot assign to read only property 'listName& ...

Add a hyperlink within a button element

I am looking to add a route to my reusable 'button' component in order to navigate to another page. I attempted using the <Link> </Link> tags, but it affected my CSS and caused the 'button' to appear small. The link works if ...

In Angular 6, triggering a reset on a reactive form will activate all necessary validators

As a beginner in angular 6, I am currently facing an issue with resetting a form after submitting data. Although everything seems to be functioning properly, when I reset the form after successfully submitting data to the database, it triggers all the req ...

What is the method for obtaining the number of weeks since the epoch? Is it possible to

Currently, I am setting up a DynamoDb store for weekly reporting. My idea is to use the week number since 1970 as a unique identifier for each report record, similar to epoch milliseconds. Here are some questions I have: How can I determine the current w ...

Guard does not prompt router redirection

My angular app running Angular 15 is facing an issue with the App-routing module not redirecting when a guard returns the UrlTree. app-routing.module.ts import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular ...

Assigning the output of a function to an Angular2 component (written in TypeScript)

I have a small utility that receives notifications from a web socket. Whenever the fillThemSomehow() method is called, it fetches and stores them in an array. @Injectable() export class WebsocketNotificationHandler { notifications: Array<Notificati ...

Tips on enforcing Access-Control-Allow-Origin in a C# webservice hosted on IIS

I have a .net webservice running on IIS 10. My goal is to retrieve data from the backend using an Angular frontend. Access-Control-Allow-Origin is configured in IIS: https://i.sstatic.net/JeTGR.png In addition, customHeaders are set up in my Web.Conf: h ...

Encountering a service error that results in the inability to read properties of undefined when passing a method as a

Whenever I attempt to pass a service function as a parameter to another function, an error 'Cannot read properties of undefined myService' occurs during execution. However, calling this.myService.method() individually works perfectly fine without ...

I have encountered an issue while utilizing dynamic form functionality in Angular 7. The error message displayed is: "Error: Cannot find control with name: 'i'"

While working with Angular 7 dynamic forms, I encountered an error that I'm struggling to resolve. As a newcomer to Angular, this has been quite challenging for me. import { Component } from '@angular/core'; import {FormBuilder, FormArray} ...

Issues with executing code within the react package for Yahoo Finance 2

I am currently in the process of developing a React application using Vite. The purpose of my app is to retrieve stock-related information from Yahoo using the yahoo-finance2 package. Interestingly, when I run the code as a standalone JavaScript file, eve ...

Exploring the @HostBinding argument in Angular directives

Need help grasping the concept behind the @Hostbinding argument: Snippet of the code: import { Directive, HostBinding } from "@angular/core"; @Directive({ selector: '[appDropdown]' }) export class DropdownDirective { @HostBinding(&apos ...

What is the process for configuring vue.config.js with typescript?

Just starting out with typescript and running into an issue while configuring vue.config.js const webpack = require("webpack"); module.exports = { plugins: [ new webpack.DefinePlugin({ __VUE_I18N_FULL_INSTALL__: true, __ ...

Property 'map' is not recognized on type 'Object' and needs to be addressed

I am currently using Angular CLI: 6.0.8 and have implemented the service shown below. However, my code editor's linter keeps showing an error message that reads: [ts] Property 'map' does not exist on type 'Object'. any The error ...

Updating the text area value based on the selected option in a dropdown using Typescript within Angular6

I'm currently facing an issue with updating the text area value based on the selection from a dropdown menu. Below is the design of the dialog: https://i.sstatic.net/67U1M.png Here's the code snippet I've incorporated for this functionalit ...