Creating Composite Components in Angular

前端 未结 1 1804
南方客
南方客 2021-01-15 04:39

I want to create a Angular generic composite component which is composed of bunch of input fields which could be used inside multiple components across applicat

相关标签:
1条回答
  • 2021-01-15 04:55

    So, to your child components you can pass form and add/remove controls to him.

    Parent component template

    <form (ngSubmit)="onSubmit(form)" #form="ngForm">
            <a-comp [prop1]="name" [form]=form></a-comp>
    
          <button type="submit">Submit</button>
     </form>
    

    Some child component:

    // a comp
    @Component({
      selector: 'a-comp',
      template: `
        <input [(ngModel)]="prop1"  name="name2" #myControl="ngModel"/>
        `
    
    })
    export class AComponent {
      @Input() form: NgForm;
      @Input() prop1 = 'Angular 5';
    
      @ViewChild('myControl') myControl: NgModel;
    
      ngOnInit() {
        //console.log(this.form, this.myControl);
        this.form.addControl(this.myControl);
    
    
      }
    }
    

    CODE EXAMPLE

    Passing @Input to childs isn't necessary. But child components need to know about form.

    2. Easiest way. By using power of DI

    Child-component. In your case UserDetails:

    @Component({
      selector: 'a-comp',
      viewProviders: [{ provide: ControlContainer, useExisting: NgForm }],
      template: `
          <input [(ngModel)]="prop1"  name="prop1"/>
          <input [(ngModel)]="prop2"  name="prop2"/>
        `
    
    })
    export class AComponent {
      prop1 = 'Hello';
      prop2 = 'World';
    
      ngOnInit() { }
    }
    

    As you can see in @Component decorators we set viewProviders. So when requiring ControlContainer we say to useExisting: NgForm. By Angular DI system it will go up to find first parent NgForm.

    ViewProviders = Defines the set of injectable objects that are visible to its view DOM children.

    ...

    You maybe can ask: By DI mechanism it should search provider up to root, but why it doesn't go up in hirearchy and find parent NgForm?

    Constuctor of ngModel:

     constructor(@Optional() @Host() parent: ControlContainer,
                  @Optional() @Self() @Inject(NG_VALIDATORS) validators: Array<Validator|ValidatorFn>,
                  @Optional() @Self() @Inject(NG_ASYNC_VALIDATORS) asyncValidators: Array<AsyncValidator|AsyncValidatorFn>,
                  @Optional() @Self() @Inject(NG_VALUE_ACCESSOR)
                  valueAccessors: ControlValueAccessor[]) {
    ...
    

    Pay attention to @Optional() @Host() parent: ControlContainer. It's @Optional and @Host().

    @Host - Specifies that an injector should retrieve a dependency from any injector until reaching the host element of the current component.

    So, here @Host() decorators restrics the ngModel to search only up to host component where ngModel is allocated.

    NgModel constructor

    By this approach no need create @Input binding in child components to get parent NgForm and add NgModels controls manually.

    StackBlitz EXAMPLE

    0 讨论(0)
提交回复
热议问题