Je souhaite modifier (forcer) les valeurs des champs de saisie lors de la frappe à l'aide d'un attribut Directive. Avec cela, je voudrais créer des directives comme majuscules, minuscules, maxlength, filterchar, etc. à utiliser sur les champs de saisie des formulaires. J'ai trouvé cet exemple: Angular 2 Attribut Directive TypeScript Exemple mais cela ne semble pas fonctionner. Peut-être que c'était le cas pour une version antérieure d'Angular2. C'est pourtant exactement ce que j'aimerais faire.
Quand je crée une directive comme celle-ci:
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 utilisez-le sur un formulaire comme celui-ci:
<input type="text" class="form-control" [(ngModel)]="field.name" ngControl="name" #name="ngForm" required uppercase>
(et enregistrez NgModel
en tant que fournisseur). Je reçois un
undefined this.model.value.
Je peux utiliser $event.target.value = $event.target.value.toUpperCase()
(lorsque je passe $event
avec onInputChange()
) et cela fonctionne pour la vue (il affiche l'entrée en majuscule. Mais il ne met pas à jour le champ de liaison "field.name".
Alors, comment créer une directive d'attribut Angular2 qui fait cela?
-- MODIFIER --
Après une enquête plus poussée, j'ai réussi à obtenir ce que je voulais. La réponse fournie par Günter est plus proche de mon intention initiale et peut-être meilleure. Mais voici un autre moyen:
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 un bon moyen de le faire, alors les commentaires sont les bienvenus.
mettre à jour
Cette approche ne fonctionne pas correctement. Voir la réponse de @ RyanHow pour une meilleure solution.
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());
}
}
Bien que la réponse de Günter semble prometteuse, il y a un bug dans le fait que la dernière valeur entrée dans le modèle est la dernière lettre entrée en minuscule.
Vois ici:
https://plnkr.co/edit/SzxO2Ykg2pKq1qfgKVMH
Veuillez utiliser la réponse fournie dans la question. Cela 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)
}
}
J'ai fait face au même problème, où je dois créer la sélection personnalisée dans Angular avec select2 . J'ai créé ce qui suit pour y parvenir avec directive d'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());
}
});
}
}
avec l'usage suivant
<select custom-select [(ngModel)]="protocol.type">
<option value="1">option1</option>
<option value="1">option2</option>
</select>
L'exigence que je devais créer une directive pour rogner les espaces de début et de fin pour la saisie de texte ..__ ma 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);
}
}