2017-12-26 25 views
2

私は角度成分を持っています。これは実際にはブートストラップパネルです。テンプレートと角度指示出力出力、親が更新されない

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> 

とディレクティブは、ブートストラップ崩壊イベント(jqueryの)を検出し、それらにcollapseStatus($event)の私のコンポーネントを伝搬するcollapseControl呼ば:

@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)"に変更するだけで問題ありません。これは角度変化の検出で何かをしなければならないが、私が間違っていることを理解することはできない。

+0

「jquery」タグは質問に関係しますか? –

+0

はい、jqueryを使用してブートストラップイベントをキャプチャします – MartinM

答えて

1

Angularは、zone内で発生していないので、Observable.fromEventサブスクリプションを通じて行われた変更を認識していません。 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、可能であれば、折り畳み式などで作業するときに角のような経験を増やすために

+0

あなたの答えはありがとうございます。私はangleが 'Observable.fromEvent'について知らないと理解していますが、実際にシグナルを送出するEventEmitterを認識し、元のイベントとは基本的に関係のない' toggleActive'ハンドラで値が更新されると思います。これを説明できますか? – MartinM

+1

はい、 'EventEmitter'の* aware *ですが、変更検知の意味ではありません。通常、 'emit'はゾーン内から(例えばXHRやDOMイベントの後に)呼び出されますが、Angularがこれらのイベントが発生したときに耳を傾ける魔法はありません。 'emit'はゾーン内にあります。 –

+1

@MartinMでは、[単方向データフローとは何を意味するのか本当に分かっていますか?](https://blog.angularindepth.com/do-you-really-know-what-一方向データフロー手段内角度α6f55cefdc63) –

関連する問題