异步输入未更新Angular2

时间:2017-05-01 09:20:25

标签: angular asynchronous

我试图检索父组件中的某些数据并在子组件中使用它。但是未检测到更改(未触发ngOnChanges)。

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>

已更新

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;
      }
      );
  }
}

更新2

如果我使用zone.run()它可以工作(但我仍然不知道为什么我必须这样做)

parent.component.ts

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

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  
 }
}

1 个答案:

答案 0 :(得分:1)

尝试手动触发更改检测

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();
});