1

I'm trying to retrieve some data in a parent component and use it in a child component. But changes are not detected (ngOnChanges is not fired).

parent.component.ts

@Component({
  selector: 'parent',
  templateUrl: './parent.component.html'
})
export class ParentComponent {
  countries: VisitedCountries;
  @ViewChild('childModalComponent')
  childModalComponent: ChildModalComponent;


  openChildModal() {
    this.childModalComponent.openModal();
  }

  displayProfil() {
    var that = this;

   // If I put this here, child component has an updated variable => ngOnChanges is fired
   // this.countries = new VisitedCountries(...)

    this.userService.getUserProfil()
      .then(result => {
            // this.countries is not updated in child component
            that.countries = new VisitedCountries(result) as VisitedCountries;

      });
  }
}

parent.component.html

<span (click)="openChildModal()">
<child-modal [countries]="countries"> </child-modal>

UPDATED

childModal.component.ts

@Component({
  selector: 'child-modal',
  templateUrl: './childModal.component.html'
})
export class ChildModalComponent implements OnInit, OnChanges {
  @Input()
  countries: VisitedCountries;
  selectedCountries: Country[];

  ngOnChanges(changes: SimpleChanges) {
   // not fired with async content
  }

  openModal() {
    this.selectedCountries = [];

    // simplified algo
    for (country in this.countries) {
      this.selectedCountries.push(country); 
    }

    // this.selectedCountries is well filled at this point
  }

}

childModal.component.html

<modal>
  ...
    // primeng autocomplete
    <p-autoComplete [(ngModel)]="selectedCountries" [suggestions]="filteredCountriesMultiple" field="label" (completeMethod)="filterCountryMultiple($event)"
        [multiple]="true">
    </p-autoComplete>

 ...
</modal>

user.service.ts

@Injectable()
export class UserService {
  getUserProfil(userId: string) {
    return this.http.get(url)
      .toPromise()
      .then(response => response.json() as User)
      .catch(error => {
        return error;
      }
      );
  }
}

UPDATE 2

If I use zone.run() it works (but I still don't know why I have to do this)

parent.component.ts

@Component({
  selector: 'parent',
  templateUrl: './parent.component.html'
})
export class ParentComponent {
  function () {
    this.zone.run(() => this.displayProfil());
  }
}

and

childModal.component.ts

@Component({
  selector: 'child-modal',
  templateUrl: './childModal.component.html'
})
export class ChildModalComponent implements OnInit, OnChanges {
  @Input()
  countries: VisitedCountries;
  selectedCountries: Country[];

  openModal() {
    this.selectedCountries = [];
    this.zone.run(() => {
      // I had another async call here
      service.getObject().then (() => {
        for (country in this.countries) {
          this.selectedCountries.push(country); 
        }
      });
    }); 

   // or this.ref.detectChanges(); also works  
 }
}
2
  • Can you create a plunker that reproduces your issue? Commented May 1, 2017 at 10:28
  • Check Zone.current.name Commented May 1, 2017 at 17:34

1 Answer 1

1

Try triggering change detection manually

import {ChangeDetectorRef} from '@angular/core'

export class ParentComponent {

  constructor(private cdr: ChangeDetectorRef){}

  ...

this.userService.getUserProfil()
  .then(result => {
        // this.countries is not updated in child component
        that.countries = new VisitedCountries(result) as VisitedCountries;
        this.cdr.detectChanges();
});
Sign up to request clarification or add additional context in comments.

11 Comments

What did I break in my code that force me to detect some changes manually ? I tried to add this line "this.cdr.detectChanges();" before. ngOnChanges is fired in the child component, but view is not updated with the correct value
@isy can you include the view too then?
@isy where do you call openModal() ? Your selectedCountries is empty until that point
openModal is called from the parent with 'openChildModal' when user clicks on an edit button to display a modal (i've updated my code again).
@isy ok what do you expect to see inside the view?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.