Solución:
aquí hay una solución genérica (directiva) para pasar al siguiente tipo de control similar cuando alcanza la longitud máxima
1- Crea la Directiva
import { Directive, HostListener } from '@angular/core';
@Directive({
selector: 'input[moveNextByMaxLength], textarea[moveNextByMaxLength]',
})
export class MoveNextByMaxLengthDirective {
@HostListener('keyup', ['$event']) onKeyDown(keyboardEvent: KeyboardEvent) {
const target = keyboardEvent.target as
| HTMLInputElement
| HTMLTextAreaElement
| null;
if (!target || target.maxLength !== target.value.length) return;
keyboardEvent.preventDefault();
const { type } = target;
let { nextElementSibling } = target;
while (nextElementSibling) {
if (
(nextElementSibling as HTMLInputElement | HTMLTextAreaElement).type ===
type
) {
(nextElementSibling as HTMLInputElement | HTMLTextAreaElement).focus();
return;
}
nextElementSibling = nextElementSibling.nextElementSibling;
}
}
}
2- Declarar la Directiva en el módulo
@NgModule({
imports: [ BrowserModule ],
declarations: [
AppComponent,
MoveNextByMaxLengthDirective
],
bootstrap: [ AppComponent ]
})
3- Utilice la directiva en el componente
<input formControlName="day" maxlength="2" moveNextByMaxLength placeholder="DD" type="text" (keyup)="keytab($event)" />
<input formControlName="month" maxlength="2" moveNextByMaxLength placeholder="MM" type="text" (keyup)="keytab($event)" />
<input formControlName="year" maxlength="4" placeholder="YYYY" type="text" />
Utilice un enfoque diferente. Angular no selecciona elementos ni lee atributos del DOM existente, como lo hace jQuery, porque Angular genera el DOM a partir de datos. Por lo que es difícil, si es posible, leer la entrada maxlength
atributo, y de todos modos sería torpe un “no Angular”.
En su lugar, utilice un enfoque diferente y pase maxLength en el keyup
función:
<input type="text" (keyup)="keytab($event, 2)" />
<input type="text" (keyup)="keytab($event, 4)" />
keytab(event, maxLength){
console.log(maxlength); // 2 or 4
// .......
}
Solo una idea, pero si está utilizando formas reactivas, podría hacer algo como esto:
import { FormGroup, FormBuilder, Validators } from "@angular/forms";
import { Component, OnInit, ViewChild, ElementRef } from "@angular/core";
import { filter } "rxjs/operators";
@Component({
selector: "app-form",
template: `
<form [formGroup]="form">
<input formControlName="day" placeholder="DD" type="text" #day />
<input formControlName="month" placeholder="MM" type="text" #month />
<input formControlName="year" placeholder="YYYY" type="text" #year />
</form>
`
})
export class FormComponent implements OnInit {
form: FormGroup;
@ViewChild("day") dayElement: ElementRef;
@ViewChild("month") monthElement: ElementRef;
@ViewChild("year") yearElement: ElementRef;
constructor(private fb: FormBuilder) {}
ngOnInit() {
const dayMaxLength = 2;
const monthMaxLength = 2;
const yearMaxLength = 4;
this.form = this.fb.group({
day: ["", [Validators.required, Validators.maxLength(dayMaxLength)]],
month: ["", [Validators.required, Validators.maxLength(monthMaxLength)]],
year: ["", [Validators.required, Validators.maxLength(yearMaxLength)]]
});
this.form.get("day").valueChanges
.pipe(filter((value: string) => value.length === dayMaxLength))
.subscribe(() => this.monthElement.nativeElement.focus());
this.form.get("month").valueChanges
.pipe(filter((value: string) => value.length === monthMaxLength))
.subscribe(() => this.yearElement.nativeElement.focus());
}
Básicamente, suscríbase a los cambios de valor de los controles de formulario de día y mes, filtre cada flujo para que solo continúe cuando el valor sea igual a la longitud máxima, luego establezca el foco en el siguiente elemento. Probablemente valga la pena señalar que también será necesario cancelar la suscripción a estos.