Angular 异步输入未更新2

Angular 异步输入未更新2,angular,asynchronous,Angular,Asynchronous,我试图在父组件中检索一些数据,并在子组件中使用它。但未检测到更改(未触发ngOnChanges) parent.component.ts @Component({ selector: 'parent', templateUrl: './parent.component.html' }) export class ParentComponent { countries: VisitedCountries; @ViewChild('childModalComponent') ch

我试图在父组件中检索一些数据,并在子组件中使用它。但未检测到更改(未触发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;

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

}
@Injectable()
export class UserService {
  getUserProfil(userId: string) {
    return this.http.get(url)
      .toPromise()
      .then(response => response.json() as User)
      .catch(error => {
        return error;
      }
      );
  }
}
@Component({
  selector: 'parent',
  templateUrl: './parent.component.html'
})
export class ParentComponent {
  function () {
    this.zone.run(() => this.displayProfil());
  }
}
@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  
 }
}
parent.component.html

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

 ...
</modal>
childModal.component.html

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

 ...
</modal>
更新2

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

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;

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

}
@Injectable()
export class UserService {
  getUserProfil(userId: string) {
    return this.http.get(url)
      .toPromise()
      .then(response => response.json() as User)
      .catch(error => {
        return error;
      }
      );
  }
}
@Component({
  selector: 'parent',
  templateUrl: './parent.component.html'
})
export class ParentComponent {
  function () {
    this.zone.run(() => this.displayProfil());
  }
}
@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  
 }
}

childModal.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;

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

}
@Injectable()
export class UserService {
  getUserProfil(userId: string) {
    return this.http.get(url)
      .toPromise()
      .then(response => response.json() as User)
      .catch(error => {
        return error;
      }
      );
  }
}
@Component({
  selector: 'parent',
  templateUrl: './parent.component.html'
})
export class ParentComponent {
  function () {
    this.zone.run(() => this.displayProfil());
  }
}
@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  
 }
}

尝试手动触发更改检测

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

我在代码中破坏了什么,迫使我手动检测某些更改?我试图在前面添加这一行“this.cdr.detectChanges();”。ngOnChanges在子组件中激发,但视图未使用正确的value@isy那么您也可以包含视图吗?@isy您在哪里调用
openModal()
?您的
selectedCountries
是空的,直到当用户单击编辑按钮以显示模式(我再次更新了代码)时,从父级调用该点OpenModel(openChildModal)为止。@y确定您希望在视图中看到什么?您能创建一个复制您的问题的plunker吗?检查
Zone.current.name