【问题标题】:ngModelChange get called on keypress even though not fired from ngModelChange.emit()即使没有从 ngModelChange.emit() 触发,也会在按键上调用 ngModelChange
【发布时间】:2017-06-15 19:34:52
【问题描述】:

我正在尝试调用 ngModelChange 事件,但仅在我使用时调用它

this.ngModelChange.emit(data)

现在每次我敲击键盘上的键以及使用上一个命令调用它时都会调用它。为什么?

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

字段组件:

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) 来删除数据,在点击事件时,它会调用函数 onSelect(data)。这部分工作得很好。

不起作用的是,在每次击键时都会调用 Field 组件中的函数 onChange(),并在 Autocomplete 组件中的函数 setData() 之前使用输入字符串中的值。如何删除对 onChange() 的不需要的调用?

提前致谢

你可以去看看 plunker to 一个例子:https://plnkr.co/edit/jAVIupQ2R1Vm1y9YHoLI?p=preview

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

【问题讨论】:

    标签: angular


    【解决方案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

    【讨论】:

    • 它不起作用,因为 onChange 被调用了两次。一次用于带有字符串参数的按键,第二次来自 this.ngModelChange.emit(data)。
    • 你能用 plunker 复制它吗?
    • 我已经更新了我的问题以添加 plunker 和一些解释。
    • 查看我的更新答案。您的 autocomplete.js 中存在错误,并且使用了一些“错误”的角度名称出现了一些奇怪的行为。
    • 谢谢,你想要这样,对吧? plnkr.co/edit/MwhStfLsumz74lG9311l?p=preview
    猜你喜欢
    • 2013-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-10
    • 1970-01-01
    • 2021-04-02
    相关资源
    最近更新 更多