简体   繁体   English

使用ngModel更改字段值的属性指令

[英]Attribute directive with ngModel to change field value

I want to change (force) input field values while typing using a attribute Directive. 我想在使用属性Directive键入时更改(强制)输入字段值。 With it I would like to create directives like uppercase, lowercase, maxlength, filterchar, etc. to be used on input fields on forms. 有了它,我想创建一些指令,如大写,小写,maxlength,filterchar等,用于表单上的输入字段。 I found this example: Angular 2 Attribute Directive Typescript Example but this doesn't seem to work. 我找到了这个例子: Angular 2 Attribute Directive Typescript Example但这似乎不起作用。 Maybe it did for an earlier build of Angular2. 也许它是为早期构建的Angular2做的。 It is however exactly what I would like to do. 然而,这正是我想要做的。

When I create a directive like this: 当我创建这样的指令时:

import {Directive} from 'angular2/core';
import {NgModel} from 'angular2/common';

@Directive({ 
selector: '[ngModel][uppercase]', 
host: {
    '(input)' : 'onInputChange()'
      }
})
export class UppercaseDirective{

constructor(public model:NgModel){}

onInputChange(){
    var newValue = this.model.value.toUpperCase();
    this.model.valueAccessor.writeValue(newValue);
    this.model.viewToModelUpdate(newValue);
    }
}

And use it on a form like this: 并在这样的表单上使用它:

<input type="text" class="form-control" [(ngModel)]="field.name" ngControl="name" #name="ngForm" required uppercase>

(and register NgModel as a provider). (并将NgModel注册为提供者)。 I get an 我得到了

undefined this.model.value. undefined this.model.value。

I can use $event.target.value = $event.target.value.toUpperCase() (when passing $event with the onInputChange() ) and that works for the view (it does show the input as uppercase. But it doesn't update the bind field "field.name". 我可以使用$event.target.value = $event.target.value.toUpperCase() (当使用onInputChange()传递$event时)并且适用于视图(它确实将输入显示为大写。但它没有' t更新绑定字段“field.name”。

So how to create an Angular2 attribute directive that does this? 那么如何创建一个Angular2属性指令呢?

-- EDIT -- - 编辑 -

After some further investigation I managed to get what I want. 经过一番进一步调查后,我设法得到了我想要的东西。 The answer Günter provided is closer to my original intention and perhaps better. Günter提供的答案更接近我的初衷,也许更好。 But here is another way: 但这是另一种方式:

import {Directive, Input, Output, EventEmitter} from 'angular2/core';

@Directive({ 
selector: '[ngModel][uppercase]',
host: {
"(input)": 'onInputChange($event)'
    }
})
export class UppercaseDirective{
@Output() ngModelChange:EventEmitter<any> = new EventEmitter()
value: any

onInputChange($event){
    this.value = $event.target.value.toUpperCase()
    this.ngModelChange.emit(this.value)
    }
}

As I said I'm not sure if this is also a good way to do this so comments are welcome. 正如我所说,我不确定这是否也是一个好方法,所以欢迎评论。

Although Günter's answer looks promising, there is a bug in that the final value in the model has the last entered letter in lowercase. 尽管Günter的答案看起来很有希望,但是有一个错误,即模型中的最终值以小写字母输入最后一个字母。

See here: 看这里:

https://plnkr.co/edit/SzxO2Ykg2pKq1qfgKVMH https://plnkr.co/edit/SzxO2Ykg2pKq1qfgKVMH

Please use the answer provided in the question. 请使用问题中提供的答案。 It works correctly. 它工作正常。

@Directive({ 
selector: '[ngModel][uppercase]',
host: {
"(input)": 'onInputChange($event)'
    }
})
export class UppercaseDirective{
@Output() ngModelChange:EventEmitter<any> = new EventEmitter()
value: any

onInputChange($event){
    this.value = $event.target.value.toUpperCase()
    this.ngModelChange.emit(this.value)
    }
}

https://plnkr.co/edit/oE3KNMCG7bvEj8FV07RV https://plnkr.co/edit/oE3KNMCG7bvEj8FV07RV

update 更新

This approach doesn't work properly. 这种方法不能正常工作。 See @RyanHow's answer for a better solution. 请参阅@ RyanHow的答案以获得更好的解决方案。

original 原版的

@Directive({ 
  selector: '[ngModel][uppercase]',
  providers: [NgModel],
  host: {
    '(ngModelChange)' : 'onInputChange($event)'
  }
})
export class UppercaseDirective{
  constructor(private model:NgModel){}

  onInputChange(event){
    this.model.valueAccessor.writeValue(event.toUpperCase());
  }
}

Plunker Plunker

I have faced the same issue, where I need to create the custom select in Angular with select2 . 我遇到了同样的问题,我需要使用select2在Angular中创建自定义选择。 I have created following directive thing to achieve this with attribute directive and ngModel . 我已经使用attribute指令和ngModel创建了以下指令来实现这ngModel

import {ElementRef, Directive, EventEmitter, Output, Input} from '@angular/core';
import {NgModel} from "@angular/forms";
declare let $;
@Directive({
  selector: '[custom-select]',
  providers: [NgModel]
})
export class CustomSelectComponent{
  $eventSelect:any;
  @Output() ngModelChange:EventEmitter<any> = new EventEmitter();
  @Input() set ngModel(value:any){
    //listen to the input value change of ngModel and change in the plugin accordingly.
    if(this.$eventSelect){
      this.$eventSelect.val(value).trigger('change',{fromComponent:true});
    }
  }
  constructor(private elementRef: ElementRef) {}
  ngOnInit(){
    this.$eventSelect = $(this.elementRef.nativeElement);
    this.$eventSelect.select2({minimumResultsForSearch:-1});
    this.$eventSelect.on("change.select2", (event,data)=> {
      //listen to the select change event and chanage the model value 
      if(!data || !data.fromComponent){ //dont change model when its chagned from the input change event
        this.ngModelChange.emit(this.$eventSelect.val());
      }
    });
  }
}

with following usage 以下用法

<select custom-select [(ngModel)]="protocol.type">
  <option value="1">option1</option>
  <option value="1">option2</option>
</select>

The requirement I had to create a directive to trim the leading and trailing spaces for text input. 要求我必须创建一个指令来修剪文本输入的前导和尾随空格。 my solution: 我的解决方案

import { Directive, ElementRef, HostListener, Output, EventEmitter } from '@angular/core';
import { NgModel } from "@angular/forms";

@Directive({
    selector: '[text-trim]',
    providers: [NgModel]
})

export class TextInputTrimDirective {

@Output() ngModelChange: EventEmitter<any> = new EventEmitter();

constructor(private el: ElementRef) {}

@HostListener('change') onInputChange() {
    const value = this.el.nativeElement.value.trim();
    this.ngModelChange.emit(value);
}
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM