Angular2:EventEmitter有时会触发,有时不会触发

时间:2017-01-07 16:06:38

标签: javascript angular eventemitter angular2-components

组件的EventEmitter在某些情况下会触发,但在其他情况下则不会。为什么呢?

我有一个自定义日期选择器。您可以手动更改日期(<input>)或使用ng2-bootstrap <datepicker>方便地进行选择。

我有这个模板:

<input [(ngModel)]="dateString"
    class="form-control"
    (focus)="showPopup()"
    (change)="inputChange()">
<datepicker class="popup" [ngClass]="{ 'popup-hidden': !showDatepicker }"
    [(ngModel)]="dateModel"
    [showWeeks]="true"
    (ngModelChange)="hidePopup($event)">
</datepicker>

具有相关部分的组件:

export class CustomDatepickerComponent {
    @Input()
    dateModel: Date;
    dateString: string;

    showDatepicker = false;

    @Output()
    dateModelChange: EventEmitter<Date> = new EventEmitter();

    showPopup() {
        this.showDatepicker = true;
    }

    // Called when the date is changed manually
    // It DOES fire the event
    inputChange() {
        let result = moment(this.dateString, 'YYYY-MM-DD');
        this.update(result.toDate());
    }

    // Called through the DatePicker of ng-bootstrap
    // It DOESN'T fire the event
    // However, the showDatepicker binding takes effect (see template)
    hidePopup(event: Date) {
        showDatepicker = false;
        this.update(event);
    }

    update(date: Date) {
        this.dateModel = date;
        this.dateString = moment(date).format('YYYY-MM-DD');
        // This SHOULD fire the event
        // It is called in BOTH cases! 
        // But it fires only when the date is changed through the <input>
        this.dateModelChange.emit(this.dateModel);
    }

我用这种方式使用这个日期选择器:

<custom-datepicker [dateModel]="testDate" (change)="change($event)"></custom-datepicker>

这是change()处理函数。

    testDate = new Date();
    change($event) { console.info('CHANGE', $event); }

有什么想法吗?

3 个答案:

答案 0 :(得分:0)

好的......现在这有点令人尴尬。 这是该组件的用法:

custom-datepicker [dateModel]="testDate" (change)="change($event)"></custom-datepicker>

应改为:

custom-datepicker [dateModel]="testDate" (dateModelChange)="change($event)"></custom-datepicker>

有趣的是,changed元素的<input>事件似乎从CustomDatepickerComponent冒出来了。它是在组件内部处理的,它触发了未处理的dateModelChange,然后它作为change事件冒泡到外部组件 - 这样它就被处理了。

如果我将事件传递给inputChange()并调用event.stopPropagation(),则会被取消并且不会传播。

再一次:它与EventEmitter无关。

答案 1 :(得分:0)

我有一个类似的问题。我通过将@ainput日期模型(datemodel)与datepicker中使用的日期模型(localdate:Date;)分离来解决它 然后我使用ngOnChange保持这两个变量同步。这样,EventEmitter工作正常,并为每个日期选择或更新发送一个值。

export class myDatepicker implements OnChanges{
  localdate: Date;

  @Input() datemodel: Date;
  @Input() isOpen: boolean = false;
  @Input() label: string;
  @Input() disabled: boolean = false;


  @Output() datemodelChange: EventEmitter<Date> = new EventEmitter<Date>();

  // Date has been selected in Datepicker, emit event
  public selectedDate(value: any) {

    this.datemodelChange.emit(value);
}

// React on changes in the connected input property
ngOnChanges(changes: { [propName: string]: SimpleChange }) {

    try {
        if (changes["datemodel"] && changes["datemodel"].currentValue) {
            this.localdate = moment(changes["datemodel"].currentValue).toDate();                // raw Input value
        }
    } catch (ex) {
        console.log('myDatePicker: ' + ex);
    }
}

}

答案 2 :(得分:0)

为在此页面上绊脚的人提供的另一种解决方案。

我有一个类似的问题,这也不是EventEmitter的错。 :-) 最初似乎是我的EventEmitter间歇性地没有触发,但是罪魁祸首是负责触发EventEmitter的点击处理程序。

我的html模板中有这个

<button mat-mini-fab color="primary">
    <i class="fas fa-pencil-alt" (click)="onClickEdit()"></i>
</button>

和点击处理程序:

  export class MyClass {
  @Output() edit = new EventEmitter();

  constructor() { }

  onClickEdit() {
    console.log('onClickEdit(), this.edit=' + this.edit);
    this.edit.emit();
  }
}

我添加了console.log()来调试问题,并且我发现每次单击精美的编辑图标时均不会触发onClickEdit(),这解释了为何未触发EventEmitter的原因。 :-)

我通过将(click)属性移到封闭按钮上来解决了这个问题(事后看来,这很明显。)

<button mat-mini-fab color="primary" (click)="onClickEdit()">
    <i class="fas fa-pencil-alt"></i>
</button>

问题解决了。