Angular 指令发出输出,父级未更新

Angular directive emitting output, parent not updated

我有一个 angular 组件,它实际上是一个 bootstrap 面板。

export class ExerciseComponent implements OnInit {
  @Input() exercise:Exercise;
  @Input() index:number;
  @Input() first:boolean;
  @Input() last:boolean;
  @Input() active:boolean;
  @Input() selected:boolean;
  constructor(private data:ApiDataService, private route:ActivatedRoute) {
  }

  toggleActive(e){
    let show = (e.type=='show');
    this.active = show;
  }
}

使用模板:

<div class="panel-heading">
  <div>
    <h5 class="panel-title">
      <a data-toggle="collapse" data-parent="#accordionexercises"
         class="accordion-link" href="#collapse{{ exercise.id }}">
        {{ exercise.title }} </a>
    </h5>
    <div class="pull-right">
      <i *ngFor="let n of exercise.difficulty | fill" class="fa fa-star"></i>
    </div>
  </div>
  <exercise-preview [hidden]="active" [e]="exercise"></exercise-preview>
</div>
<div id="collapse{{ exercise.id }}" [ngClass]="{'panel-collapse collapse':true, 'in':selected}"
     collapseControl (collapseStatus)="toggleActive($event)">
  <div class="panel-body">
    <div class="row">
      <div class="col-md-12">
        <div *ngIf="exercise.image" class="pull-right">
          <img src="http://localhost:8000{{ exercise.image.file }}"/>
        </div>
        <div [innerHtml]="exercise.exText"></div>
      </div>
    </div>
  </div>
</div>

和一个名为 collapseControl 的指令,它检测 bootstrap 崩溃事件(Jquery)并将它们传播到我在 collapseStatus($event) 中的组件:

@Directive({
  selector: '[collapseControl]'
})
export class CollapseControlDirective{
  @Output() collapseStatus: EventEmitter<any>;

  constructor(el: ElementRef) {
    this.collapseStatus = new EventEmitter();
    Observable
      .fromEvent($(el.nativeElement), 'hide.bs.collapse show.bs.collapse')
      .subscribe(e=> this.collapseStatus.emit(e));
  }
}

一切正常,事件传播到父级,this.active 根据事件设置,但 UI 未更新(注意 [hidden] 属性 <exercise-preview/> 组件).

如果我只是将 (collapseStatus)="toggleActive($event)" 更改为 (click)="toggleActive($event)" 一切正常。这与 angular 变化检测有关,但我不知道我做错了什么。

Angular 不知道通过 Observable.fromEvent 订阅所做的更改,因为这不会在区域中的 zone. You can use NgZone 到 运行 代码中发生.例如:

import { NgZone } from '@angular/core';

// ...

constructor(el: ElementRef, ngZone: NgZone) {
    this.collapseStatus = new EventEmitter();
    Observable
      .fromEvent($(el.nativeElement), 'hide.bs.collapse show.bs.collapse')
      .subscribe(e => {
          ngZone.run(() => this.collapseStatus.emit(e));
      });
}

您最好使用例如ng-bootstrap,如果可以的话,为了在使用可折叠物等时获得更 Angular 的体验