Angular structural directice shorthand template does not works while complete template works...

Discussão em 'Angular' iniciado por dmi, Outubro 14, 2024.

  1. dmi

    dmi Guest

    For display validation messages of reactive form control i started to develop structural directive in Angular 18 with source code below

    import { Directive, effect, input, InputSignal, TemplateRef, ViewContainerRef } from '@angular/core';
    import { AbstractControl, FormGroup } from '@angular/forms';

    @Directive({
    selector: '[appValidationMessages]',
    standalone: true
    })

    export class ValidationMessagesDirective {
    constructor(
    private templateReference: TemplateRef<{
    $implicit: {
    key: string;
    message: string}
    }>,
    private viewContainerReference : ViewContainerRef) {
    effect(() => {
    const controlReference = this.appValidationMessagesOf().get(this.appValidationMessagesControlName());
    if (!controlReference) {
    throw new Error(`Control with name ${this.appValidationMessagesControlName} not found in form group`);
    }
    this.control = controlReference;
    this.control.statusChanges.subscribe(() => {
    this.doValidation();
    });
    });

    }

    public appValidationMessagesControlName : InputSignal<string> = input<string>('');

    public appValidationMessagesOf : InputSignal<FormGroup> = input.required<FormGroup>();

    private control: AbstractControl<any, any> ;

    private doValidation() : void {

    if(!this.control || !this.control.touched || !this.control.errors) {
    this.viewContainerReference.clear();
    return;
    }
    this.viewContainerReference.clear();
    for(const key in this.control.errors) {
    let error = 'This field is invalid';
    switch(key) {
    case 'required':
    error = 'This field is required';
    break;
    case 'email':
    error ='This field must be a valid email address';
    break;
    case 'minlength':
    error = `This field must be at least ${this.control.errors['minlength'].requiredLength} characters long`;
    break;
    case 'emailIsTaken':
    error = 'This email is already taken';
    break;

    }
    const viewData = {$implicit : {key: key, message: error}};
    this.viewContainerReference.createEmbeddedView(this.templateReference, viewData );
    }
    }
    }


    When i use it with ng-template, it works like expected.

    <section>
    <header>Validation messages complete</header>
    <ng-template appValidationMessages let-valMessages [appValidationMessagesOf]="loginForm" appValidationMessagesControlName="email">
    <p class="text-danger">{{valMessages.message}}</p>
    </ng-template>
    </section>


    But, when i try to use it with * syntax

    <section>
    <header>Validation messages shorthand</header>
    <p class="text-danger" *appValidationMessages="let valMessages of loginForm" appValidationMessagesControlName="email" >{{valMessages.message}}</p>
    </section>


    I receive a message

    ERROR Error: Control with name function inputValueFn() {
    producerAccessed(node);
    if (node.value === REQUIRED_UNSET_VALUE) {
    throw new RuntimeError(-950, ngDevMode && "Input is required but no value is available yet.");
    }
    return node.value;
    } not found in form group
    at EffectHandle.effectFn (validation-mesages.directive.ts:19:25)
    at EffectHandle.runEffect (core.mjs:14336:18)
    at Object.fn (core.mjs:14331:58)
    at Object.run (signals.mjs:514:18)
    at EffectHandle.run (core.mjs:14346:22)
    at ZoneAwareEffectScheduler.flushQueue (core.mjs:14314:20)
    at core.mjs:14304:41
    at _ZoneDelegate.invoke (zone.js:368:26)
    at Object.onInvoke (core.mjs:14832:33)


    I suppose i missed a convention for shorthand template, but what exactly and how to fix it? Thank you.

    Continue reading...

Compartilhe esta Página