首页 > 解决方案 > 如何限制 Angular 输入框中的输入并保持模型正确?

问题描述

我很难实现与以前来自 AngularJS 的解析器和格式化程序的等价物。我的用例不是直接的解析器/格式化程序,但这是我想要完成的。

我有一个动态的列表。对于这些键中的每一个,用户可以输入一个 0-100 的值。如果用户输入(键盘或粘贴)任何字符,它们将被删除。如果用户输入任何大于 100 的数字,则其上限为 100。

为此,我创建了一个过滤掉我需要的指令。该指令在input元素上正常工作,但底层form没有获得正确的值,如下所示。

糟糕的形式

无论如何,表格似乎得到了我的最后一个输入。

如何防止更新模型以获取无效值?

我为此创建了一个StackBlitz。代码的要点是:

app.component.html

<form #form="ngForm">
  <div *ngFor="let key of list">
  <input name="{{key}}" ngModel appFilter >
  </div>
</form>

<pre>
form:
{{ form.value | json }}
</pre>

app.component.ts

export class AppComponent  {
  readonly list = ['foo', 'bar'];
}

filter.directive.ts

@Directive({
    selector: 'input[appFilter]',
})
export class FilterDirective {
    // TODO: remove directive?
    @Output()
    ngModelChange: EventEmitter<any> = new EventEmitter();

    value: string;

    @HostListener('input', ['$event'])
    onInputChange($event: TextInput) {
        const filtered = $event.target.value.replace(/[^0-9]/gi, '');
        if (filtered.match(/^[0-9]/)) {
            // starts with a number, must be a number
            const number = +filtered.replace(/\*/gi, '');
            $event.target.value = `${Math.min(100, number)}`;
        } else {
            // it must be empty string
            $event.target.value = '';
        }
        this.ngModelChange.emit($event.target.value);
    }
    constructor() {}
}

interface TextInput {
    target: {
        value: string;
    };
}

标签: angularangular-forms

解决方案


通过使用$event.target.value您可以调整input's 的值,而不是基础 Angular 的值NgControl。幸运的是,只要with属性还具有关联的或属性,NgControl就可以将其注入到您的指令中。inputappFilterngModelformControlformControlName

注入NgControl您的FilterDirective并使用它来设置值:

import { NgControl } from '@angular/forms';

constructor(private ngControl: NgControl) { }

@HostListener('input', ['$event'])
onInputChange($event: TextInput) {
    const filtered = $event.target.value.replace(/[^0-9]/gi, '');
    if (filtered.match(/^[0-9]/)) {
        // starts with a number, must be a number
        const number = +filtered.replace(/\*/gi, '');
        this.ngControl.control.setValue(`${Math.min(100, number)}`);
    } else {
        // it must be empty string
        this.ngControl.control.setValue('');
    }
}

您是否应该期望在FilterDirective没有ngModel,formControlformControlName属性的情况下使用您的情况?然后制作注入的 NgControl @Optional()


推荐阅读