0

ChangeDetectionAngular2 は、クリック イベントの後をトリガーしません。以下のコード スニペットは、あるコンポーネントから別のコンポーネントにデータを取得するためのものです。

onClickEvent

 (click)="$event.preventDefault(); setApartmentObject(FlatObject)";

アパートの概要コンポーネント

constructor(private _apart:ApartmentService) {}

setApartmentObject(flat:ApartmentObject) {
    this._apart.setApartmentDetails(flat);
}

アパートサービス

Injectable()
export class ApartmentService {

  apartmentDetails:ApartmentObject

  getApartmentDetails():Observable<ApartmentObject> {
      return Observable.create((observer) => {
          observer.next(this.apartmentDetails);
          observer.complete();
      });
  }

  setApartmentDetails(value:ApartmentObject) {
      this.apartmentDetails = value;
  }
}

ApartmentDetailComponent

constructor(private _apart:ApartmentService)

get apartmentDetails() {
    this._apart.getApartmentDetails().subscribe(data => {
        this._apartmentDetails = data;
    });
    return this._apartmentDetails;
}

HTMLファイル内

 <p><strong>{{apartmentDetails.name || 'Musterwohnung'}}</strong></p>

また、イベントエミッターを使用してこの問題を修正しようとしましたが、成功しませんでした。次のダーティ フィックスのみが機能します。

constructor(private _ref:ChangeDetectorRef) {
  this._ref.detach();
  setInterval(() => {
     this._ref.detectChanges();
  }, 300);
}
4

1 に答える 1

2

コードには、値の読み取りを実際に妨げる問題がいくつかあります。

まず第一に、サービスで値を設定するときは、監視可能なオブジェクトに値を与えるのではなく、サービスのインスタンスで行うだけです。オブザーバブルは値が変更されたことを認識できないため、変更 (次の) イベントを発行しません。これが、ApartmentOverviewComponent. setApartmentObject()が何もしない理由です。オブザーバブルに実際にデータを供給するには、サブジェクトを使用する必要があります。

ApartmentDetailComponent では、この単純なシナリオ (データが常に同期的に提供される) で、試してみた方法で値を取得できました。ただし、前述のとおり、データは変更されません。コンポーネントのインスタンスの_apartmentDetailsフィールドにデータを保存することも重要です。テンプレートでオブザーバブルを使用できます。

実際の実装は次のようになります。

@Injectable()
class ApartmentService {
  // BehaviorSubject is a type of an Observable that can be manually fed with data
  // and returns it's last value to any subscriber.
  apartmentDetails = new BehaviorSubject<ApartmentObject>({name: 'Musterwohnung'});

  // Instead of using a property of the service, just inform the
  // subject about knew data and let it spread the change for you.
  setApartmentDetails(value: ApartmentObject) {
    this.apartmentDetails.next(value);
  }
}

@Component({
  selector: 'overview-cmp',
  // Side note: you don't need to .preventDefault() here.
  template: `<a (click)="setApartmentObject({name: 'Shiny Aparament'})">click</a>`
})
class ApartmentOverviewComponent {
  constructor(private apartService: ApartmentService) {}

  // Works same as before.
  setApartmentObject(flat: ApartmentObject) {
    this.apartService.setApartmentDetails(flat);
  }
}

@Component({
  selector: 'details-cmp',
  // Use the 'async' pipe to access the data stored in an Observable
  // object. Also, to secure the code, use '?' to safely access the property.
  template: `<p><strong>{{(details | async)?.name}}</strong></p>`
})
class Apartament {
  // This is the observable with data.
  details: Observable<ApartmentObject>;

  constructor(private apartService: ApartmentService) {}

  // When component initialises, assign the observable data from the service
  ngOnInit() {
    this.details = this.apartService.apartmentDetails;
  }
}
于 2016-07-22T20:28:57.557 に答える