【问题标题】:How to update ngModel from directive?如何从指令更新 ngModel?
【发布时间】:2018-04-09 13:15:56
【问题描述】:

我创建了一个指令来限制input 字段type=number 的长度。

// 输入

<input min="1" appLimitTo [limit]="5" type="number" name="property" [(ngModel)]="property">

// 指令

import {Directive, HostListener, Input} from '@angular/core';

@Directive({
  selector: '[appLimitTo]',
})
export class LimitToDirective {

    @Input() limit: number;
    @Input() ngModel: any;

    @HostListener('input', ['$event'])
    onInput(e) {
        if (e.target.value.length >= +this.limit) {
            e.target.value = (e.target.value).toString().slice(0, this.limit - 1);
            e.preventDefault();
        }
    }
}

如果我们通过键盘输入值,它就可以正常工作。但是,如果我复制并粘贴 12345678913465789 这个数字,这一行 e.target.value = (e.target.value).toString().slice(0, this.limit - 1); 将其缩短到极限,但 ngModel 仍然包含 12345678913465789 值,就会出现问题。如何更新这个 ngModel 值?

请帮忙。

PS - 我应该在指令中添加什么以满足要求?

【问题讨论】:

  • Angular 指令@output

标签: angular input dom-events angular2-directives


【解决方案1】:

您可以将NgControl 注入您自己的指令中。然后就可以监听valueChanges控件的事件了。

limit-to.directive.ts

import {Directive, HostListener, Input, OnInit, OnDestroy} from '@angular/core';
import {NgControl} from '@angular/forms';
import {map} from 'rxjs/operators';
import {Subscription} from 'rxjs/Subscription';

@Directive({
  selector: '[appLimitTo]',
})
export class LimitToDirective implements OnInit, OnDestroy {
    @Input('appLimitTo') limit: number;

    private subscription: Subscription;

    constructor(private ngControl: NgControl) {}

    ngOnInit() {
      const ctrl = this.ngControl.control;

      this.subscription = ctrl.valueChanges
        .pipe(map(v => (v || '').toString().slice(0, this.limit)))
        .subscribe(v => ctrl.setValue(v, { emitEvent: false }));
    }

    ngOnDestroy() {
      this.subscription.unsubscribe();
    }
}

用法:

<input ngModel appLimitTo="3" type="number" />

Live demo

【讨论】:

  • 您可能已经将ngModel 初始化为null。查看我的编辑。 map 函数现在看起来像这样:map(v =&gt; (v || '').slice(0, this.limit))
  • 没有检查过...不是那样...我尝试使用 if 检查v 但仍然出现相同的错误...有没有其他方法可以做所以....使用ElementRef 和事件?
  • 请注意,您应该在销毁时取消订阅以避免内存泄漏
  • 仅供参考。 OP 正在使用type="number,所以这个解决方案会抛出 OP 提到的错误。这个 stackblitz 之所以有效,是因为它不是类型号。通过将(v || '').slice 更改为(v || '').toString().slice 可以轻松修复它。
  • 已修复。谢谢你的评论:)
猜你喜欢
  • 2014-08-23
  • 2015-01-01
  • 2023-03-11
  • 1970-01-01
  • 2017-07-25
  • 2015-01-24
  • 1970-01-01
  • 2019-03-28
  • 2016-08-10
相关资源
最近更新 更多