【问题标题】:How to call @Input EventEmitter from parent in Angular 2如何在Angular 2中从父级调用@Input EventEmitter
【发布时间】:2017-05-19 09:43:30
【问题描述】:

您好,我有一个带有以下@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' });

【问题讨论】:

    标签: javascript angularjs input eventemitter


    【解决方案1】:

    如果您的子组件有:

    @Input x(): number;
    

    然后你被要求将一个值从父组件传递给子组件:

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

    其中“myVariable”表示类型为“number”的变量。在您的情况下,您的输入名为“inputEvents”,类型为“EventEmitter&lt;{ type: string, data: string | DateModel }&gt;”。因此,从您的父组件中,您将传递相同的输入。

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

    其中变量“toggleCalEvent”的类型为“EventEmitter&lt;{ type: string, data: string | DateModel }&gt;”,在您的父组件上也是如此:

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

    然后你可以像调用任何 EventEmitter 一样调用这个 EventEmitter:

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

    由于 datepicker 订阅了这个 'inputEvents',那么当你触发一个 'next' 时,它会在 child 中触发这个事件。但是还有一个问题。如果您在单击某物时触发此事件,它将不起作用。试试这个:

    <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();
    }
    

    现在日历显示按预期切换。

    【讨论】:

      【解决方案2】:

      Angular 建议为此使用 ngOnChange() 事件:

      OnChanges
      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;
              }
      
          }
      
      }
      

      【讨论】:

        【解决方案3】:

        虽然 ngChanges 是可能的,但我不喜欢开销和通常的性能损失。我最喜欢处理父驱动事件的设计模式是输入设置器:

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

        触发主题

        checkVisibility$ = new Subject<boolean>();
        

        我在 onInit 方法中订阅的

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

        编辑:当然,您也可以使用 NGXS 之类的东西,调度一个事件并在您的孩子中捕获它。但是对于简单且通常与表单和模板相关的事件,我发现上述方法效果很好。

        【讨论】:

          猜你喜欢
          • 2017-01-28
          • 2018-11-17
          • 1970-01-01
          • 2017-04-04
          • 2016-07-29
          • 1970-01-01
          • 2016-10-04
          • 2020-01-30
          • 2017-01-03
          相关资源
          最近更新 更多