Tengo un campo de texto representado como: field = {text: "", valid: false} , y una entrada con [(ngModel)]="field.text" .
Quiero hacer que ese campo solo acepte un conjunto definido de caracteres (para este problema, números), y hacer (keypress) no funciona en dispositivos móviles, así que lo hice: (ngModelChange)="fieldChanged(field)"
El método hace lo siguiente:
fieldChanged(field) { console.log(field.text); field.text = Array.from(field.text).filter((char:string) => "0123456789".indexOf(char) != -1).join(""); console.log(field.text); }Y su comportamiento es extremadamente extraño.
Leyenda: - entrada: qué tecla se presionó - antes de la actualización: primera console.log - después de la actualización: segunda console.log - salida: lo que veo en pantalla en la entrada
| input | before update | after update | output | |---------|---------------|--------------|--------| | "" | "" | "" | "" | <- starting position, no event | "a" | "a" | "" | "a" | | "a" | "aa" | "" | "aa" | | "4" | "aa4" | "4" | "4" | | "a" | "4a" | "4" | "4a" | | "a" | "4aa" | "4" | "4aa" | | "4" | "4aa4" | "44" | "44" |¿Por qué siempre actualiza la salida cuando ingreso un carácter legal? Debería estar funcionando para cada llamada de evento.
Editar: Plunker
Creo que la causa es que modificar el valor en ngModelChange rompe la detección de cambios, por ejemplo, si cambia el valor al valor anterior, porque se agregó un carácter no válido.
Una solución:
constructor(private cdRef:ChangeDetectorRef) {} fieldChanged(field) { console.log(field.text); field.text = Array.from(field.text).filter((char:string) => "0123456789".indexOf(char) != -1).join(""); console.log(field.text); var tmp = field.text; field.text = null; // or some other value that normally won't ever be in `field.text` this.cdRef.detectChanges(); field.text = tmp; this.cdRef.detectChanges(); // I guess this 2nd call won't be necessary }Si alguien tiene problemas para actualizar el valor, use la función setTimeout mientras actualiza
// setTimeout function setTimeout(() => { field.text = temp; this.cdRef.detectChanges(); }, 1);