Hice un formulario simple en el que debo ingresar un número de teléfono dividido en tres secciones, la primera entrada toma 3, la segunda entrada toma 3 y la última debe tomar 4. He establecido la maxlength para los elementos de entrada, estoy llamando al keyup para enfocarme en al siguiente elemento. Pero en lugar de 3 trazos, salta a la siguiente entrada después de ingresar un solo número.
Aquí está mi caja de códigos para que juegues
Aquí está mi HTML
<div class="form-group" style="height:70px;"> <label class="reg_txt">Phone Number <span>*</span></label> <div class="clearfix"></div> <div class="wsite-form"> <input type="text" class="text input-name1" formControlName="phone1" maxlength="3" (keyup)="nextStep($event,1)" (focus)="focused(1)" id="code1"> </div> <div class="line">-</div> <div class="wsite-form"> <input type="text" class="text input-name1" formControlName="phone2" maxlength="3" (keyup)="nextStep($event,2)" (focus)="focused(2)" id="code2"> </div> <div class="line">-</div> <div class="wsite-form"> <input type="text" class="text input-name1" formControlName="phone3" maxlength="4" (keyup)="nextStep($event,3)" (focus)="focused(3)" id="code3"> </div> </div>Aquí está mi método de componente
nextStep(event, step: number): void { const prevElement = document.getElementById('code' + (step - 1)); const nextElement = document.getElementById('code' + (step + 1)); console.log(event) if (event.code == 'Backspace' && event.target.value === '') { event.target.parentElement.parentElement.children[step - 2 > 0 ? step - 2 : 0].children[0].value = '' if (prevElement) { prevElement.focus() return } } else { if (nextElement) { nextElement.focus() return } else { } } }y también si presiono la tecla de retroceso, debería saltar al elemento anterior, funciona para el segundo cuadro de entrada y arroja un error para el último elemento. Sé que cometí un error tonto, ¿alguien podría indicarme la dirección correcta? Agradeceré cualquier ayuda.
También puede crear una directiva (*) como
@Directive({ selector: 'input[maxlength]', exportAs: 'child' }) export class MaxLengthDirective { @Input()prev:HTMLElement; @Input()next:HTMLElement; @HostListener('keyup',['$event']) _(event:any){ if (!event.target.value && this.prev && event.key=='Backspace') this.prev.focus() if (event.target.value.length==this.maxLength && this.next) this.next.focus() } constructor(@Attribute('maxlength') private maxLength:number){} }Puedes usar como
<input #one maxlength="3" [next]="two"> <input #two [prev]="one" [next]="three" maxlength="4"> <input #three [prev]="two" maxlength="5">Ver el stackbliz
(*) No olvide incluir en las declaraciones de su módulo
Actualizar Sí, también creo que es un poco complejo usar las variables de referencia de la plantilla y [prev] y [next] así que, ¿por qué no mejorar?
Para esto usamos dos directivas
@Directive({ selector: 'input[maxlength]', exportAs: 'child' }) export class MaxLengthDirective { @HostListener('keyup',['$event']) _(event:any){ if (!event.target.value && event.key=='Backspace') this.parent.prev(this) if (event.target.value.length==this.maxLength) this.parent.next(this) } constructor(@Attribute('maxlength') private maxLength:number,@Optional() @Host() private parent:MaxLengthGroupDirective,public elementRef:ElementRef){ } } @Directive({ selector: '[maxLengthGroup]', exportAs: 'maxLengthGroup' }) export class MaxLengthGroupDirective { @ContentChildren(MaxLengthDirective) items:QueryList<MaxLengthDirective> next(item:MaxLengthDirective) { const index=this.items.toArray().findIndex(x=>x==item); if (index<this.items.length-1) { const nextItem=this.items.find((_,i)=>i>index) nextItem.elementRef.nativeElement.focus() } } prev(item:MaxLengthDirective) { const index=this.items.toArray().findIndex(x=>x==item); if (index>0) { const prevItem=this.items.find((_,i)=>i==index-1) prevItem.elementRef.nativeElement.focus() } } } El grupo de longitud máxima obtiene la longitud máxima mediante ContentChildren. Entonces tenemos en una QueryList todas las entradas que tienen matlength. Dos funciones dentro de "next" y "prev" son las que se enfocan en el elemento anterior o siguiente. Para esto, necesitamos inyectar en mat-length el max-length-group usando @Host que le indica a Angular que busque esta directiva. El uso es como
<div max-length-group> <input maxlength="3" placeholder="max 3" /> <input placeholder="max 4" maxlength="4" /> <input placeholder="max 5" maxlength="5" /> </div>Agregar esto if (nextElement && event.target.value.length === 3) a su declaración else en la parte inferior de nextStep() funciona en lugar de solo if (nextElement) .
Si hay un siguiente elemento al que ir y la longitud actual de la entrada es 3, enfóquese en el siguiente elemento.