web-dev-qa-db-ja.com

フィールド値を変更するngModelを使用した属性ディレクティブ

属性ディレクティブを使用して入力中に入力フィールド値を変更(強制)したい。それを使用して、フォームの入力フィールドで使用される大文字、小文字、maxlength、filtercharなどのディレクティブを作成したいと思います。私はこの例を見つけました: Angular 2 Attribute Directive TypeScript Example しかしこれはうまくいかないようです。たぶん、Angular2の以前のビルドでした。しかし、それはまさに私がやりたいことです。

このようなディレクティブを作成すると:

_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);
    }
}
_

そして、次のようなフォームで使用します。

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

(およびNgModelをプロバイダーとして登録します)。私は

未定義のthis.model.value。

$event.target.value = $event.target.value.toUpperCase()(_$event_をonInputChange()で渡す場合)を使用できます。これはビューに対して機能します(入力を大文字で表示します。ただし、バインドフィールドは更新しません。 "フィールド名"。

それで、これを行うAngular2属性ディレクティブを作成する方法は?

-編集-

いくつかのさらなる調査の後、私は自分が欲しいものを得ることができました。ギュンターが提供した答えは、私の当初の意図により近く、おそらくより良いものです。しかし、別の方法があります:

_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)
    }
}
_

私が言ったように、これがこれを行う良い方法であるかどうかわからないので、コメントを歓迎します。

18
majodi

update

このアプローチは適切に機能しません。より良い解決策については、@ RyanHowの回答を参照してください。

オリジナル

@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

12

Günterの答えは有望に見えますが、モデルの最終値には最後に入力された文字が小文字になるというバグがあります。

こちらをご覧ください:

https://plnkr.co/edit/SzxO2Ykg2pKq1qfgKVMH

質問に記載されている回答を使用してください。正常に動作します。

@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

30
Ryan How

Angular with select2 でカスタム選択を作成する必要がある同じ問題に直面しました。属性ディレクティブと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());
      }
    });
  }
}

次の使用法で

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

要件は、テキスト入力の先頭と末尾のスペースをトリミングするディレクティブを作成する必要がありました。私の解決策:

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);
}
}
0
Ali Jamal