Directive d'attribut avec ngModel pour changer la valeur du champ

je veux modifier (forcer) les valeurs des champs d'entrée en tapant à l'aide d'une directive d'attribut. Avec cela je voudrais créer des directives comme uppercase, lowercase, maxlength, filterchar, etc. à utiliser dans les champs d'entrée des formulaires. J'ai trouvé ça par exemple: Angular 2 Attribut Directive Typescript Example mais cela ne semble pas fonctionner. Peut-être pour une construction antérieure D'Angular2. Il est cependant exactement ce que je voudrais faire.

Quand je crée une directive comme ceci:

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

Et l'utiliser dans un formulaire comme ceci:

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

(et vous inscrire NgModel en tant que fournisseur). Je reçois un

undefined.modèle.valeur.

je peux utiliser $event.target.value = $event.target.value.toUpperCase() (lors du passage d' $eventonInputChange()) et cela fonctionne pour la vue (cela montre l'entrée en majuscules. Mais il ne met pas à jour le champ "bind field".nom".

alors comment créer une directive d'attribut Angular2 qui ne cette?

-- EDIT --

Après quelques recherches, j'ai réussi à obtenir ce que je veux. La réponse fournie par Günter est plus proche de mon intention initiale et peut-être meilleure. Mais voici une autre façon:

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

comme je l'ai dit, Je ne suis pas sûr que ce soit aussi une bonne façon de le faire, donc les commentaires sont les bienvenus.

17
demandé sur majodi 2016-03-19 22:46:26

3 réponses

mise à jour

Cette approche ne fonctionne pas correctement. Voir la réponse de @RyanHow pour une meilleure solution.

origine

@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
répondu Günter Zöchbauer 2016-10-21 16:04:26

bien que la réponse de Günter semble prometteuse, il y a un bug dans le fait que la valeur finale dans le modèle a la dernière lettre entrée en minuscules.

Voir ici:

https://plnkr.co/edit/SzxO2Ykg2pKq1qfgKVMH

veuillez utiliser la réponse fournie dans la question. Il fonctionne correctement.

@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

25
répondu Ryan How 2018-03-16 12:01:54

J'ai fait face au même problème, où je dois créer le Select personnalisé en angle avec select2. J'ai créé la chose directive suivante pour réaliser ceci avec la directive attribut et 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());
      }
    });
  }
}

de l'utilisation suivante

<select custom-select [(ngModel)]="protocol.type">
  <option value="1">option1</option>
  <option value="1">option2</option>
</select>
1
répondu Dinesh Dabhi 2017-12-30 00:38:19