Search code examples
angularinheritanceangular-reactive-forms

Pass a param to component Providers In Angular


I have a Component that inherits from another -

@Component({
  template: '',
  providers: [
    {
        provide: NG_VALUE_ACCESSOR,
        useExisting: forwardRef(() => TComp),        
        multi: true,
      },
  ]
})
export abstract class FormBase<TComp> implements ControlValueAccessor {
   ...
   ...
}

And Another component -

@Component({
   selector: 'app-button',
   templateUrl: './button.component.html',
   styleUrls: ['./button.component.scss'],
})
export class ButtomComponent extends FormBase<ButtomComponent> {
   ...
   ...
}

I want to be able to pass a reference of child component to parent component, so parent can add the provider instead of child (which may look as shown above), I want to extend this behavior and inherit the FormBase in other components and avoid declaring the NG_VALUE_ACCESSOR provider in every child component,

I couldn't find a proper way to do it, I get an error cannot find name - TComp, Will appreciate your help!


Solution

  • When you inherit a class, it does not inherit the @Component decorator contents, so any way you look at it, you never import the parent contents outside the class, so you have to declare them individually.

    You can just write a utility function that will reduce your code size, like shown below

    utility

    export const addProviders = (component: any) => {
      return {
        provide: NG_VALUE_ACCESSOR,
        useExisting: forwardRef(() => component),
        multi: true,
      };
    };
    

    child component

    import { CommonModule } from '@angular/common';
    import { Component } from '@angular/core';
    import {
      FormsModule,
      ReactiveFormsModule,
    } from '@angular/forms';
    import { addProviders, ParentComponent } from '../parent/parent.component';
    
    @Component({
      selector: 'app-child',
      templateUrl: './child.component.html',
      styleUrls: ['./child.component.css'],
      standalone: true,
      providers: [addProviders(ChildComponent)],
      imports: [CommonModule, FormsModule, ReactiveFormsModule, ParentComponent],
    })
    export class ChildComponent extends ParentComponent {
      constructor() {
        super();
      }
    
      ngOnInit() {}
    }
    

    stackblitz