Tengo un <form> que utiliza el enfoque basado en plantillas.
El formulario contiene una combinación de controles nativos, como <input> y <select> , y también componentes envolventes, como <text-control> y <checkbox-control> que contienen el elemento nativo <input> dentro de él.
¿Cómo puede el formulario acceder al elemento nativo de <text-control> para leer su error y estado tocado?
Además, si quiero colocar una directiva de validación en ese componente contenedor y hacer que se canalice hacia el <input> nativo, ¿cómo puedo abordar esto?
Traté de usar ngModel en el componente contenedor, pero no funciona, ya que ngModel se conecta al componente contenedor, no al elemento <input> subyacente.
Otro enfoque fue usar <ng-content> , pero el elemento nativo subyacente toma muchos atributos, tanto que será una molestia copiarlo y pegarlo en todas partes.
Ejemplo:
<checkbox-control> <!-- Now, it's easy for the form to access the control. --> <!-- But I've too many attributes and properties that go here. --> <input type="checkbox"> </checkbox-control> PD: no estoy buscando usar ElementRef para acceder al elemento nativo, solo quiero que <form> esté al tanto del estado de error de los elementos nativos, para que pueda saber si el formulario es válido o no.
Ejemplo:
<form #editor="ngForm"> <input type="text" validateText /> <select validateSelect> <option value="1"></option> <option value="2"></option> </select> <!-- Does not work. --> <checkbox-control validateCheckbox></checkbox-control> </form>Gracias por adelantado.
Encontré una solución razonable que funciona sin escribir mucho código y sin editar demasiados componentes.
Paso 1: crea tu validador
@Directive({ selector: '[assertNoSpecialChars]' }) export class SpecialCharacterValidator implements Validator { // The directive will have a reference for the name of the form's control. @Input() assertNoSpecialChars: string = ''; validate(group: FormGroup): ValidationErrors | null { const control = group.controls[this.assertNoSpecialChars]; // For simplicity, let's say we don't want the dollar sign in our input. if (control.value.includes('$')) { return { invalid: true }; } else { return null; } } }Paso 2: aplique la directiva en su formulario
<form #f="ngForm" [assertNoSpecialChars]="'username'"> <text-control></text-control> </form>Paso 3: vincule el evento de entrada de su componente al componente del formulario de alojamiento
<form #f="ngForm" [assertNoSpecialChars]="'username'"> <text-control (input)="updateFormManually($event, 'username')"></text-control> </form>Paso 4: obtenga una referencia para su NgForm e implemente el mecanismo de actualización
@Component({}) export class FormComponent implements AfterViewInit { // Grab a reference for your NgForm. @ViewChild('f', { static: true }) f!: NgForm; // Create your form control. username: FormControl = new FormControl(); // Register your control to the NgForm. ngAfterViewInit(): void { this.f.form.addControl('username', this.username); } // Update the control manually. updateFormManually(event: any, controlName: string): void { this.f.form.controls[controlName].setValue(event.target.value); } }Ahora, el estado de validez del formulario y los mensajes de error se vincularán correctamente.
Puede usar la referencia local del elemento en el enfoque de plantilla. Consulte este código que acabo de escribir para explicar:
https://stackblitz.com/edit/angular-ivy-7no9ok?file=src/app/app.component.html