即使没有从ngModelChange.emit()触发,也会在keypress上调用ngModelChange

时间:2017-01-30 15:19:44

标签: angular

我试图调用ngModelChange事件但仅在我用

调用它时
this.ngModelChange.emit(data)

现在,每当我按下键盘上的按键并且使用上一个命令调用它时,它就会被调用。为什么呢?

我有一个组件' Feild'其中我根据传递的类型属性创建不同类型的输入。其中一个是我在JQuery中创建的自动完成组件。为了使它与angular一起工作,我创建了一个组件来将值传递给它。

现场组件:

import { Component, Input, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'field',
  template: `<div class="field">
                <div class="fieldTitle" *ngIf="text">{{text}}</div>
                <div class="fieldValue" *ngIf="type">
                    <input *ngIf="type == 'text'" type="text" [ngModel]="ngModel" (ngModelChange)="onChange($event)" [name]="name" ngDefaultControl/>
                    <autocomplete *ngIf="type == 'autocomplete'" [link]="link" [mapping]="mapping" [ngModel]="ngModel" (ngModelChange)="onChange($event)" [name]="name" ngDefaultControl></autocomplete>
                </div>
            </div>`
})
export class Field{
    @Input() text: string;
    @Input() type: string;
    @Input() ngModel: any;
    @Input() name: string;
    @Input() mapping: string;
    @Input() link: string;

    @Output() ngModelChange = new EventEmitter();

    constructor(){

    }

    onChange(e){
        this.ngModel = e;
        this.ngModelChange.emit(e);
    }
}

自动填充组件:

import { Component, Input, ViewChild, Output, EventEmitter} from '@angular/core';

@Component({
  selector: 'autocomplete',
  template: `<div #autocomplete class='autoComplete'></div>`
})
export class AutoComplete{
    @Input() ngModel: any;
    @Input() link: string;
    @Input() mapping: string;

    @ViewChild('autocomplete') content: any;

    @Output() ngModelChange = new EventEmitter();
    @Output() select = new EventEmitter();

    constructor(){

    }
    ngAfterViewInit(){
        var ctrl = this;
        var options = {
            link: this.link,
            mapping: this.mapping,
            data: this.ngModel,

            onSelect: function(data: any){
                ctrl.ngModel = data;
                ctrl.ngModelChange.emit(data);
                ctrl.select.emit({data: data});
            },
            setData: function(e : any){
                ctrl.ngModel = e;
                ctrl.ngModelChange.emit(e);
            }
        }

        for(var key in options) {
            if(options[key] === undefined){
                delete options[key];
            }
        }

        $(this.content.nativeElement).autoComplete(options);
    }
}

我的自动填充会生成一些带有其他div和样式的输入。当我在里面输入内容时,它会过滤数据列表并仅显示那些在输入中匹配字符串的数据。单击结果时,它会将数据设置为我单击的数据。在每个按键上,它调用setData(undefined)来删除数据,在click事件中它调用onSelect(data)函数。那部分工作正常。

工作原理是,来自Field组件的onChange()函数在每次击键时被调用,其中输入字符串中的值来自Autocomplete组件中的函数setData()。如何删除对onChange()的不需要的调用?

提前致谢

你可以在一个例子中检查一下:https://plnkr.co/edit/jAVIupQ2R1Vm1y9YHoLI?p=preview

如果查看控制台,您将看到字符串并且未定义。字符串与输入中的字符串相同,未定义的是自动完成返回的字符串。 undefined很好但不是字符串。我花了一段时间才使它成功。事实证明,只要导入FormsModule就会发生这种情况。我需要FormsModule,因为我使用了与NgModel一起使用的其他类型的输入。

1 个答案:

答案 0 :(得分:1)

<强>首先

请勿使用ngModelChangengModel等保留角度词语。

似乎会导致意想不到的行为!!

<强>第二

autocomplete工作正常,无法设置当前值。

修复它:

obj.search = function (reinitialize) {
   obj.options.data = obj.input[0].value; // NEW !!
      if (reinitialize === true) {
         //obj.options.data = undefined; // ?!?!?!? WHY ??

这是一个有效的演示:https://plnkr.co/edit/2H0GRSp3ktJWoMSWDe7S?p=preview

<强>第三

最好是实施正确的ngModel支持。你必须实现ControlValueAccessor,如下所述:

https://stackoverflow.com/a/41935754/3631348