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

时间:2017-12-26 20:31:36

标签: jquery angular twitter-bootstrap components directive

我有一个角度组件,实际上是一个自举面板。

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的指令,它检测引导崩溃事件(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)",一切正常。这必须做一些角度变化检测,但我无法弄清楚我做错了什么。

1 个答案:

答案 0 :(得分:1)

Angular并不知道通过Observable.fromEvent订阅所做的更改,因为这不会在zone内发生。您可以使用NgZone在区域内运行代码。 e.g:

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的体验,等等。