简体   繁体   中英

How to nest ControlValueAccessor components in an Angular formgroup

I've got a custom component that implements ControlValueAccessor and correctly responds to updates in the parent component FormGroup and updates that FormGroup when the UI is updated.

Existing App template is like this

<form-input
   inputType="radio"
   id="method-del"
   formControlName="method"
   inputValue="Delivery"
><label>Delivery</label>
</form-input>

And the form-input:

@Component({
    selector: 'form-input',
    template: `<input #input 
                type="{{ inputType }}" 
                id="{{ id || formControlName }}"
                [value]="inputValue" 
                (blur)="onBlur($event)" 
                (keyup)="onKeyup(input.value)" 
                (focus)="onFocus(input.value)" 
                (change)="onChange($event)" 
              />`,
    providers: [
        {
            provide: NG_VALUE_ACCESSOR,
            useExisting: forwardRef(() => InputComponent),
            multi: true,
        },
    ],
})
export class InputComponent implements ControlValueAccessor, OnInit {
...
    registerOnChange(fn: any): void {
        this.onChangeCallback = fn;
    }

    registerOnTouched(fn: any): void {
        this.onTouchedCallback = fn;
    }

    writeValue(value: any): void {
        this.checked = value === this.inputValue;
    }
}

But I now need to wrap the custom component in another custom component and I can't work out how that should be done. Does the wrapping custom component now also need to implement ControlValueAccessor? If so how should the onChangeCallback in the nested custom component be hooked up to the onChangeCallback in the wrapping custom component? And should both components have a provider for NG_VALUE_ACCESSOR that forwards refs to itself? Or is there a fancy way of doing this such that the wrapping component is just a pass through?

-App (<form [formGroup=""]>
 |
  - WrappingInputComponent <-------This needs to be inserted in the chain
    |
     - FormInputComponent
       |
        - <input/>

Pass to the wrapping component the formControl using [formControl]

//wrappingInputComponent
@Input(control) control;

<form-input inputType="radio" id="method-del"
   [formControl]="control" inputValue="Delivery">
<label>Delivery</label>
</form-input>

And your app component

//App component
<form [formGroup]="form">
    <wrapping-component [control]="form.get('method')"><wrapping-component>
</form>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM