Angular 8: formControlName inside component multiple nested levels below

一笑奈何 提交于 2019-12-10 16:49:35

问题


Using this resource, I want to implement formControlName up multiple nested levels.

Angular 2 - formControlName inside component

Say the actual formGroup lives 3 component levels above a child formControlName component,

ControlValueAccessor works if the Parent component is right next to child. However multiple levels above (grandfather) form does not work.

Is there an alternative to Service, or multiple input/outputs ? Or are these the only method?

A--> Component with formGroup 
   B---> Component container
      C---> Component container
        D ---> Component with FormControlName (should pass to Component A)

Component A will collect multiple form control names from different children components similar to this,

InputText.ts

export class InputTextComponent implements  AfterViewInit, ControlValueAccessor  {
  @Input() disabled: boolean;
  @Output() saveValue = new EventEmitter();

  value: string;
  onChange: () => void;
  onTouched: () => void;

  writeValue(value: any) {
    this.value = value ? value : "";
  }

  registerOnChange(fn: any) {this.onChange = fn}

  registerOnTouched(fn: any) {this.onTouched = fn}

  setDisabledState(isDisabled) {this.disabled = isDisabled}
}

InputText.html

 <input .. />

回答1:


You can consider four options:

1) provide ControlContainer on your component with FormControlName

d.component.ts

@Component({
  ...
  viewProviders: [
    {
      provide: ControlContainer,
      useExisting: FormGroupDirective
    }
  ]
})
export class DComponent implements OnInit {

Ng-run Example

2) create simple directive that provides ControlContainer

@Directive({
  selector: '[provideContainer]',
  providers: [
    {
      provide: ControlContainer,
      useExisting: FormGroupDirective
    }
  ]
})
export class ProvideContainerDirective {
}

then place this directive somewhere at the top of nodes hierarchy in your

d.component.html

<ng-container provideContainer>
  <input formControlName="someName">
</ng-container>

Ng-run Example

3) use FormControlDirective instead of FormControlName directive

FormControlDirective requires FormControl instance to be passed

<input [formControl]="control">

You can get this instance either though DI:

d.component.ts

export class DComponent implements OnInit {
  control;
  constructor(private parentFormGroupDir: FormGroupDirective) { }

  ngOnInit() {
    this.control = this.parentFormGroupDir.control.get('someName');
  }

Ng-run Example

or use some service that ties your components.

d.component.ts

export class DComponent implements OnInit {
  control: FormControl;

  constructor(private formService: FormService) { }

  ngOnInit() {
    this.control = this.formService.get('someName');
  }

Ng-run Example

4) pass FormGroup as Input props down to the children or get it through DI or service and then wrap your input[formControlName] with formGroup directive

d.component.html

<ng-container [formGroup]="formGroup">
 <input formControlName="..."
</ng-container>

Ng-run Example




回答2:


Stackblitz

i think this is what you're looking for

follow the stackblitz example

I've created 3 components comp1 comp2 comp3

I've created the signup form in appModule and passing the formGroup to comp1 => comp2 => comp3

In comp3 I've created formControl of age property and binding it. On changing the value of age from comp3 it will get reflected in parent component, that is appComponent

Hope this helps!

Cheers!



来源:https://stackoverflow.com/questions/58707528/angular-8-formcontrolname-inside-component-multiple-nested-levels-below

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!