簡體   English   中英

如何在 Angular 2 中從父級調用 @Input EventEmitter

[英]How to call @Input EventEmitter from parent in Angular 2

嗨,我有一個帶有以下@input 的子組件:

@Input() inputEvents: EventEmitter<{ type: string, data: string | DateModel }>;

this.inputEvents.subscribe((e: any) => {
        if (e.type === 'action') {
          if (e.data === 'toggle') {
            this.toggle();
          }
          if (e.data === 'close') {
            this.close();
          }
          if (e.data === 'open') {
            this.open();
          }
        }
}

如何觸發來自父級的訂閱? 我在父組件中嘗試了以下操作,但它不起作用:

@Output() datePickerAction: EventEmitter<{ type: string, data: string }>;

this.datePickerAction.next({ type: 'action', data: 'toggle' });

如果您的子組件具有:

@Input x(): number;

然后要求您將值從父級傳遞到子級組件,如下所示:

<my-component [x]="myVariable"></my-component>

其中“ myVariable ”表示類型為“ number ”的變量。 在您的情況下,您的輸入名為“ inputEvents ”,類型為“ EventEmitter<{ type: string, data: string | DateModel }> EventEmitter<{ type: string, data: string | DateModel }> '。 因此,您將從父組件中輸入相同的內容。

<ng2-datepicker [(ngModel)]="myDate" [inputEvents]='toggleCalEvent'></ng2-datepicker>

其中變量' toggleCalEvent '的類型為' EventEmitter<{ type: string, data: string | DateModel }> EventEmitter<{ type: string, data: string | DateModel }> ',在您的父組件上也是如此:

private toggleCalEvent: EventEmitter<{ type: string, data: string | DateModel }> = new EventEmitter();

然后,您可以像任何EventEmitter一樣調用此EventEmitter:

openCal() {
     this.toggleCalEvent.next({ type: 'action', data: 'toggle' });
}

由於日期選擇器已訂閱此“ inputEvents ”,因此當您觸發“ next ”時,它將在子級中觸發此事件。 但是仍然存在一個問題。 如果單擊某件事觸發此事件,則它將不起作用。 嘗試這個:

<div 
    (click)='openCal()' 
    (mouseenter)='openCal()'
    style='background-color:yellow; width:100px; height:50px;'
></div>
<ng2-datepicker [(ngModel)]="myDate" [inputEvents]='toggleCalEvent'></ng2-datepicker>

您會看到日歷會在mouseenter上切換,但不會單擊。 這是因為如果單擊日歷之外的任何位置,日期選擇器的腳本將關閉。 因此,單擊div即可立即打開和關閉。 為防止這種情況,您可以添加以下內容以防止點擊冒泡:

<div 
    (click)='openCal($event)' 
    (mouseenter)='openCal($event)'
    style='background-color:yellow; width:100px; height:50px;'
></div>
<ng2-datepicker [(ngModel)]="myDate" [inputEvents]='toggleCalEvent'></ng2-datepicker>

openCal(e) {
    this.toggleCalEvent.next({ type: 'action', data: 'toggle' });
    e.preventDefault();
    e.stopImmediatePropagation();
}

現在,日歷顯示將按預期切換。

Angular建議為此使用ngOnChange()事件:

變更
每當Angular檢測到組件(或指令)輸入屬性的更改時,就會調用ngOnChanges方法。 此示例監視OnChanges鈎子。ngOnChanges方法采用一個對象,該對象將每個更改的屬性名稱映射到保存當前和先前屬性值的SimpleChange對象。

https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html#!#onchanges

因此,在您的情況下,您可以像這樣“訂閱”:

export class MyComponent implements OnChanges {

    @Input('parentSelection') private parentSelection;

    ngOnChanges(changes: SimpleChanges) {

        let newVal = changes['parentSelection'].currentValue;


        console.log('parent changed value to: ' + newVal);

        this.someFunction();
    }

    // depending on your needs you could also do *ngIf toggles in the template
    private someFunction() {

        switch (this.parentSelection) {

            case 'toggle':
                this.toggle();
                break;

            case 'open':
                this.open();
                break;

            case 'close':
                this.close();
                break;

            default:
                console.log("unknown event detected: " + this.childValue);
                break;
        }

    }

}

盡管 ngChanges 是一種可能性,但我不喜歡開銷和通常的性能損失。 我最喜歡的處理父驅動事件的設計模式是輸入設置器:

@Input() set checkValidityTrigger(something: boolean) {
    this.checkVisibility$.next(something);
  }

觸發主題

checkVisibility$ = new Subject<boolean>();

我在 onInit 方法中訂閱的

this.checkVisibility$
      .pipe(...)
      .subscribe();

編輯:當然,你也可以使用像 NGXS 這樣的東西,調度一個事件並在你的孩子中捕捉它。 但是對於簡單且通常與表單和模板相關的事件,我發現上述方法效果很好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM