Tengo una directiva angualr creada para convertir minúsculas a mayúsculas (sé que hay una canalización angular para esto, pero creé esta directiva para comprender los conceptos. De hecho, quiero un tipo de funcionalidad similar para otra directiva). Pero por alguna razón, esta directiva no se llama inicialmente para un valor de modelo predefinido. Sin embargo, esto se activa cuando actualizo el cuadro de texto de entrada manualmente.
Quería que una directiva angular se ejecutara al cargar la página o mostrar/ocultar la sección del componente.
En este ejemplo, quería rellenar previamente el cuadro de texto "Nombre de usuario" con "PRUEBA" en la carga de la página o en la sección mostrar/ocultar del componente (esta sección mostrar/ocultar se mostrará u ocultará en función de la respuesta de la llamada de servicio ) porque inicialicé el valor del modelo con "prueba" y definí la directiva appUpperCase en el cuadro de texto de entrada.
¿Cómo le decimos a la directiva angular que se ejecute al cargar la página o mostrar/ocultar la sección del componente?
Aquí está la directiva appUpperCase
@Directive({ selector: '[appUpperCase]' }) export class UpperCaseDirective implements OnInit { constructor(private control: NgControl) { } processInput(value: any) { return value.toUpperCase(); } @HostListener('ngModelChange', ['$event']) ngModelChange(value: any) { console.log(`directive called ${value}`); this.control.valueAccessor.writeValue(this.processInput(value)); } @HostListener('keydown.backspace', ['$event']) keydownBackspace(value: any) { this.control.valueAccessor.writeValue(this.processInput(value)); } ngOnInit(): void { } }Aquí está mi archivo html:
<form novalidate (ngSubmit)="submitForm()"> <div class="form-group row"> <label for="UserName" class="col-2 col-form-label">User Name:</label> <div class="col-4"> <input class="form-control" id="UserName" name="userName" required [(ngModel)]="userName" appUpperCase> Model: {{ userName }} </div> </div> <button class="btn btn-primary" type="submit"> Search </button> </form>y en el archivo de componentes.
userName: any; constructor() { this.userName = 'test'; }Realmente no entiendo por qué está usando HostListener (en primer lugar, para el oyente keydown.backspace, no recibe un valor en el oyente sino en el evento).
¿Por qué no simplemente escuchar el flujo valueChanges del control y actualizarlo allí?
Además, debe usar ReactiveFormsModule para que pueda obtener el valor.
// directive.ts import { Directive, OnDestroy, OnInit } from '@angular/core'; import { NgControl } from '@angular/forms'; import { Subject } from 'rxjs'; import { distinctUntilChanged, startWith, takeUntil } from 'rxjs/operators'; @Directive({ selector: '[appUpperCase]', }) export class UpperCaseDirective implements OnInit, OnDestroy { private _destroyed$ = new Subject<void>(); constructor(private control: NgControl) {} processInput(value: any) { return value.toUpperCase(); } ngOnDestroy(): void { this._destroyed$.next(); this._destroyed$.complete(); } ngOnInit(): void { this.control.valueChanges .pipe( startWith(this.control.value), distinctUntilChanged((first, second) => { return this.processInput(first) === this.processInput(second); }), takeUntil(this._destroyed$) ) .subscribe((value) => { this.control.control.setValue(this.processInput(value)); }); } } // component.ts import { Component, VERSION } from '@angular/core'; import { FormControl } from '@angular/forms'; @Component({ selector: 'my-app', templateUrl: './app.component.html', styleUrls: ['./app.component.css'], }) export class AppComponent { userName = new FormControl('test'); constructor() {} submitForm() { console.log(this.userName.value); } } <!--component.html--> <form novalidate (ngSubmit)="submitForm()"> <div class="form-group row"> <label for="UserName" class="col-2 col-form-label">User Name:</label> <div class="col-4"> <input [formControl]="userName" class="form-control" id="UserName" name="userName" required appUpperCase /> Model: {{ userName.value }} </div> </div> <button class="btn btn-primary" type="submit">Search</button> </form>