3

I'm trying to add a custom directive to the form tag and then get the inputs that use the directive formControlName to filter them by formControl and then add the mat error component dynamically to it.

I've been looking for some solutions. The best way would be that there is a token that I could use and it gets both the directive and the containerRef also so then I could filter by the directive and once I have the element use its containerRef to add to it the mat error component

@Directive({
  selector: '[appFormInstance]',
})
export class FormInstanceDirective {
  @Input('appFormInstance') form: FormGroup;

  @ViewChildren(FormControlName) formControls: QueryList<FormControlName>;
  @ViewChildren(FormControlName, { read: ViewContainerRef }) formControlContainerRefs: QueryList<ViewContainerRef>;

  createMatErrorFunction(notValidProperty: string): void {
    const matErrorFactory = this.componentFactoryResolver.resolveComponentFactory(MatError);
    const formControlName = this.formControls.find((formControl) => { return formControl.name === notValidProperty });

    // Then....???
  }
}

Well I have achieved it doing

var viewContainerRef = this.formControlContainerRefs.find((ref) => ref.element.nativeElement.getAttribute('formcontrolname') === notValidProperty);
var componentRef = viewContainerRef.createComponent(matErrorFactory);

but I still not feel comfortable with this solution.

HNL
  • 103
  • 13
  • Why? The current standard for displaying errors on a form in Angular is to place the error messages in the template markup and conditionally display them based on the state of the `formControl`. – Andrew Hill Jul 26 '19 at 14:26
  • @AndrewHill that is the idea but doing it dynamically. PS: thanks for the edits :) – HNL Jul 26 '19 at 14:31
  • It's my opinion that what you're hoping to achieve will reduce the maintainability of your codebase. You should be using `*ngIf` to add/remove components from the template. It seems like an unnecessary layer of abstraction. Future developers working on your codebase will expect to find error messages in the template - not being auto-generated by a directive. – Andrew Hill Jul 26 '19 at 14:34
  • yeah it's a design decision – HNL Jul 26 '19 at 14:47
  • 1
    It's a design decision to conditionally display elements with a directive instead of an `*ngIf`? – Andrew Hill Jul 26 '19 at 14:48
  • yeah, the idea is you add the directive to the form and sets the common formControlName to each input and then if any validation throws in the submit, it shows dynamically below the formControl that match the controlName that triggered the validation. It'll save you the time of copy and pasting the mat-error with the *ngIf to each control – HNL Jul 26 '19 at 14:59
  • It's going to take future developers more time to figure out what you're building that it'll take them to copy+paste some divs. It's a bad design decision. – Andrew Hill Jul 26 '19 at 15:02
  • Yeah, this just seems over complicated. Why not just make a custom form control with all the validation messages etc in that component, so that devs only need to copy one line, like... `` Here's one tutorial: https://blog.thoughtram.io/angular/2016/07/27/custom-form-controls-in-angular-2.html – AT82 Jul 26 '19 at 18:15

0 Answers0