Transferring information from a service to a parent component, and subsequently passing it to a child component

Hello everyone, I am a beginner with Angular and I seem to have run into an issue that I can't figure out.

In my parent component, I am attempting to pass the weekly variable to my child component but it doesn't seem to be working as expected. Here is what my parent component code looks like:

app.component.ts

import { Component } from "@angular/core";
import { GeolocationService } from "./geolocation.service";
import { WeatherService } from "./weather.service";
import { kmphToMs } from '../utilities/helpful';

@Component({
  selector: "app-root",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent {
  latitude: number;
  longitude: number;
  cityName: string;
  currentTemp: number;
  currentHumidity: number;
  currentWindSpeed: string;
  weekly: Array<object>;
  errorMessage: string;

  constructor(
    private geolocationService: GeolocationService,
    private weatherService: WeatherService
  ) {}

  ngOnInit() {
    this.geolocationService.getCoordinates().subscribe(result => {
      console.log(result);
      this.latitude = result.coords.latitude;
      this.longitude = result.coords.longitude;
      this.weatherService
        .getTheWeather(this.latitude, this.longitude)
        .subscribe(weatherData => {
          console.log(weatherData);
          this.cityName = weatherData["timezone"];
          this.currentTemp = weatherData["currently"]["temperature"];
          this.currentWindSpeed = kmphToMs(weatherData["currently"]["windSpeed"]);
          this.currentHumidity = weatherData['currently']['humidity'] * 100;
          this.weekly = weatherData['daily']['data'];
          console.table(this.weekly);
        });
    });
  }
}

app.component.html

  <app-days
    [weekly]="weekly"
  ></app-days>

Now, let's take a look at how my child component is structured:

import { Component, OnInit, Input } from "@angular/core";

@Component({
  selector: "app-days",
  templateUrl: "./days.component.html",
  styleUrls: ["./days.component.css"]
})
export class DaysComponent implements OnInit {
  @Input() weekly: Array<object>;

  constructor() {
  }

  ngOnInit() {
    console.log(this.weekly); 
  }
}

When I try to console.log the weekly variable in the child component, it shows up as undefined. I'm not sure where I might be going wrong, so any help would be greatly appreciated!

Answer №1

When working with the AppComponent, it's important to be aware that the template will begin loading before the Subscription is completed. This means that the variable weekly may be undefined until the Subscription is finished.

One way to handle this is by utilizing the ngOnChanges lifecycle hook. This function is called every time an @Input property changes within a Component. By implementing ngOnChanges in your AppComponent, you can ensure that it responds to changes in the weekly variable as soon as it is initialized.

import { Component, OnChanges, Input } from "@angular/core";

@Component({
  selector: "app-days",
  templateUrl: "./days.component.html",
  styleUrls: ["./days.component.css"]
})
export class DaysComponent implements OnChanges {
  @Input() weekly: Array<object>;

  constructor() {
  }

  ngOnChanges() {
    console.log(this.weekly); 
  }

}

To avoid encountering an undefined value, you can use the *ngIf directive in the template of your AppComponent:

<app-days *ngIf="weekly" [weekly]="weekly" ></app-days>

Answer №2

Your GEO service is currently establishing the weekly variable asynchronously. This means that when the ngOnInit method of the child components is triggered, it is probable that the asynchronous call in the parent has not yet completed.

To check if the data is being properly set, include {{weekly|json}} in your child template's HTML code for debugging purposes.

Answer №3

The issue arises from the fact that the weekly data in AppComponent is initially undefined and is only populated asynchronously from the geolocationService.getCoordinates() result.

Unfortunately, DaysComponent attempts to access the weekly data in its ngOnInit hook, which cannot guarantee that the service call has been completed.

Here are some potential solutions:

  1. Include an ngIf directive in app-days based on the existence of the weekly data. Alternatively,

  2. Implement OnChanges in DaysComponent and proceed with your tasks when the input for weekly is altered. or

  3. You can notify the change using Subject/Observable and listen for any changes in your component to react accordingly.

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

Tips for improving the performance of your Ionic 2 app

Recently, I've been working on enhancing the performance of my Ionic 2 App, particularly focusing on optimizing page loading speed. After closely analyzing the timeline of page transitions using Chrome Dev Tools, it became evident that the bottleneck ...

Why can't a TypeScript string be assigned to a union type of string literals?

I have defined a type called Direction, which is a union of the strings 'LEFT' and 'RIGHT'. However, TypeScript (tsc) is giving me an error when I try to assign a 'LEFT' string to it. Here's the code snippet: type Directi ...

What is the best way to write a function in typescript that verifies whether the argument extends a type argument and then returns the argument?

I need to create a function that checks if the argument's type extends a specific type variable and then returns the argument. Something like this: declare function checkType<T, X extends T>(argument: X): X However, TypeScript gives an error wh ...

Angular2 - How to track or listen for (click) events on dynamically inserted HTML elements

I'm trying to inject a string with a dynamically retrieved (click) event into an Angular2 template. Since this string is fetched from the back-end after the DOM is loaded, Angular doesn't recognize the injected event. Here's an example of t ...

Using Angular to import a JSON file stored locally

I am facing an issue with importing a .json file in my Angular project. The file is located outside the project structure as shown below: | common | configuration.json | angular-app | src | app | my-component | ...

Extract Method Parameter Types in Typescript from a Generic Function

Can we retrieve the type of parameters of methods from a generic interface? For instance, if we have: interface Keys { create: any; ... } type MethodNames<T> = { [P in keyof Keys]: keyof T; } Then, is it feasible to obtain the type of paramete ...

What is the best way to incorporate the C# in keyword into TypeScript?

When coding in C#, I often utilize the in keyword within conditional statements. if (1.In(1, 2) I am curious about how to implement the IN keyword in typescript. ...

The method of pausing a function until the result of another function is returned

There is a function named 'updateProfile()' that includes a condition, which checks for the value of variable 'emailChangeConfirm' obtained from another function called 'updateEmailAllProcessing()'. The issue lies in the fact ...

Challenges encountered when using promises for handling mysql query results

I've been working on creating a function that will return the value of a mysql query using promises. Here's what I have so far: query(query: string): string { var response = "No response..."; var sendRequest = (query:string): Prom ...

Angular 14 now offers ngx-pinch-zoom for an enhanced zooming experience

Is it possible to add ngx-pinch-zoom to an Angular 14 project? I encountered a peer dependency conflict when trying to install pinch-zoom with --legacy-peer-deps, which worked in the project but failed in the ci/cd pipeline due to the conflict. I attempt ...

Class with an undefined function call

Currently, I am working with angular2 and TypeScript where I have defined a class. export class Example{ //.../ const self: all = this; functionToCall(){ //.. Do somerthing } mainFunctionCall(){ somepromise.then(x => self.fu ...

Is the Angular maxlength parameter causing issues with user input?

Previously, the old ng-maxlength="5" would trigger a field error but allow user input to continue. Now, with maxlength="5", it seems that input is being prevented altogether. I have novalidate on my form - could Angular be causing this? Should input be all ...

What is the best approach to incorporate a stopwatch?

I'm exploring ways to track the time it takes for a user to click a button. While I have a working solution, I'm curious if there's a more efficient method available. Below is my current implementation: export class MainComponent implements ...

Observable in Angular 2 that emits numbers

Currently, I am working on developing a countdown timer using AngularJS 2 that starts from n=60 seconds (i.e. hh:min:sec) My implementation includes the following code: countDown: Observable<number>; count = 60; constructor() { this.countDown = O ...

Restricting types does not appear to be effective when it comes to properties that are related

I am working with a specific type that looks like this: type Props = { type: 'foo'; value: string; } | { type: 'baz'; value: number; }; However, when using a switch statement with the type property in TypeScript, the program in ...

Typescript - unexpected behavior when using imported JavaScript types:

I am struggling with headaches trying to integrate an automatically generated JavaScript library into TypeScript... I have packaged the JavaScript library and d.ts file into an npm package, installed the npm package, and the typings modules in the TypeScr ...

Angular MatDialog failing to display the gray overlay background

I am currently working with Angular 6 and have successfully integrated the theme into my project. The code snippet below shows how I open the dialog. constructor(private dialogo: MatDialog) { } ngOnInit() { this.dialogo.open(Carrega ...

Experiencing migraines while integrating Firebase 9, Redux Toolkit, and Typescript in a React project. Encountering a peculiar issue where 'dispatch' is unexpectedly identified as type 'never'?

I am currently in the process of upgrading an old project to newer technologies, specifically focusing on Typescript, redux-toolkit, and Firebase v9 for modularity. While I have limited experience with Typescript and none with redux-toolkit, I have been us ...

After updating to ionic-native 2.5.1, encountering TypeScript Error TS1005 in Ionic 2

After updating to the latest version of ionic-native (2.5.1) in my ionic 2 project, I am encountering Typescript errors when running "ionic serve" in my terminal. I have attempted to update the typescript version to 2.x but to no avail. Any assistance woul ...

Is there any way I can verify the invocation of signOut in this Jest test case?

I am attempting to perform testing on my home page within a next app. However, I have encountered an issue with a button in the Home component that triggers a logout firebase function. Despite my attempts to mock this function and verify whether or not i ...