Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular - Input data not immediately available on child component, why?

I have a child Calendar Component that receives events from his father through an input field.

@Input() private events: any[];

When the month changes the parent gets new events from an API Service and calls the child component to show them.

private populateEventsForCurrentMonth() {
return this.calendarService.getEventsAsAdmin(this.getCurrentStartDate(), 
this.getCurrentEndDate())
.then((evts) => {
  this.events = evts;
  this.calendarChild.selectEventDaysIfApplies();
})
.catch((err) => {
  console.log('error getting events', err);
});

}

But when the child tries to access the events they haven't been updated!

My workaround was wrapping the child function in a timeout of 0 milliseconds to put the entire execution at the end of the event loop.

public selectEventDaysIfApplies() {
setTimeout(() => {
  if (this.events) {
    this.events.forEach((event) => {
      let eventDate = new Date(event.starts_at);
      if (this.datesBelongToSameMonth(eventDate, this.currentDate)) {
        let dayWithEvent = this.days.find( (day) => {
          return day.number == eventDate.getDate();
        });
        if (!dayWithEvent.selected) {
          dayWithEvent.hasEvent = true;
        }
      }
    });
  }
}, 0);

}

Is there a better way of doing it? Maybe an Angular best practice that I should be implementing?

Thanks!

like image 206
Willa Avatar asked Aug 29 '17 15:08

Willa


People also ask

How do you pass input from child to parent?

1- To create a method that accepts a value and do something with it in the parent component. 2- Then pass that same method as props to the child component. 3- After that, inside the child component you pass in the email as an argument to the method sent from the parent.

How do I transfer data from parent to child in Angular 8?

Otherwise, remember the three steps: Prepare Child component to emit data. Bind Property in Parent Component template. Use Property in Parent Component class.


1 Answers

The data is not available yet, because this function is handled synchronously:

this.events = evts;
this.calendarChild.selectEventDaysIfApplies();

Immediately, after this.events has been set, the child components runs its method selectEventDaysIfApplies(). That is before the Angular change detection is run.

In my opinion, the parent component should not know about any checks and modifications its child components have to do.

A better solution would be to use the lifecycle hook OnChanges, which is triggered whenever an input of the component changes.

ngOnChanges(changes: SimpleChanges) {
  this.selectEventDaysIfApplies();
}

If your component has more than one input, you can check which one was changed.

Read more about this in the docs.

like image 134
Kim Kern Avatar answered Sep 25 '22 13:09

Kim Kern