问题
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