admin管理员组

文章数量:1390440

I have a child component that is a dropdown select and I need to add formControlName from ReactiveForms, but this dropdown is not implementing the ControlValueAccesor. When I Submit the form the error appears:

> 2025-03-14T10:21:28.237Z ERROR [src/errors/global-error-handler.ts:23:0] TypeError: dir.valueAccessor.registerOnTouched is not a function
    at cleanUpControl (forms.mjs:3151:23)
    at _FormGroupDirective.removeControl (forms.mjs:5240:5)
    at _FormControlName.ngOnDestroy (forms.mjs:5869:26)
    at executeOnDestroys (core.mjs:10462:32)
    at cleanUpView (core.mjs:10365:9)
    at destroyViewTree (core.mjs:10200:17)
    at destroyLView (core.mjs:10338:9)
    at ViewRef$1.destroy (core.mjs:13127:9)
    at ComponentRef.destroy (core.mjs:15920:23)
    at _RouterOutlet.deactivate (router.mjs:2450:22)

this Dropdown comes from a library and i tried to modify in local but is not working, the error occurs in this component.

this.form2 = new FormGroup({
            doc_dni: new FormControl('1', [Validators.required]),
            docNumber: new FormControl('', [Validators.required, Validators.pattern(PATTERNS.nif)]),
            codPostal: new FormControl(null, [Validators.required, Validators.pattern(PATTERNS.codPostal)]),
            movil: new FormControl('', [Validators.required]),
        });

and this in html:

<mac-select
    formItemUtils
    formControlName="doc_dni"
    name="documents"
    (click)="changePattern(form2.get('doc')?.value)"
    [items]="documentos"
    [placeholder]="'Comun.TipoAcceso1.PlaceHolderSelect' | translate"
    bindLabel="doc"
    bindValue="idDoc"
  >
  </mac-select>

I have a child component that is a dropdown select and I need to add formControlName from ReactiveForms, but this dropdown is not implementing the ControlValueAccesor. When I Submit the form the error appears:

> 2025-03-14T10:21:28.237Z ERROR [src/errors/global-error-handler.ts:23:0] TypeError: dir.valueAccessor.registerOnTouched is not a function
    at cleanUpControl (forms.mjs:3151:23)
    at _FormGroupDirective.removeControl (forms.mjs:5240:5)
    at _FormControlName.ngOnDestroy (forms.mjs:5869:26)
    at executeOnDestroys (core.mjs:10462:32)
    at cleanUpView (core.mjs:10365:9)
    at destroyViewTree (core.mjs:10200:17)
    at destroyLView (core.mjs:10338:9)
    at ViewRef$1.destroy (core.mjs:13127:9)
    at ComponentRef.destroy (core.mjs:15920:23)
    at _RouterOutlet.deactivate (router.mjs:2450:22)

this Dropdown comes from a library and i tried to modify in local but is not working, the error occurs in this component.

this.form2 = new FormGroup({
            doc_dni: new FormControl('1', [Validators.required]),
            docNumber: new FormControl('', [Validators.required, Validators.pattern(PATTERNS.nif)]),
            codPostal: new FormControl(null, [Validators.required, Validators.pattern(PATTERNS.codPostal)]),
            movil: new FormControl('', [Validators.required]),
        });

and this in html:

<mac-select
    formItemUtils
    formControlName="doc_dni"
    name="documents"
    (click)="changePattern(form2.get('doc')?.value)"
    [items]="documentos"
    [placeholder]="'Comun.TipoAcceso1.PlaceHolderSelect' | translate"
    bindLabel="doc"
    bindValue="idDoc"
  >
  </mac-select>
Share Improve this question edited Mar 17 at 10:17 VLAZ 29.1k9 gold badges63 silver badges84 bronze badges asked Mar 14 at 11:20 IKERAGIIKERAGI 331 silver badge3 bronze badges 2
  • kindly implement control value accessor or use ngModel? – Naren Murali Commented Mar 14 at 11:22
  • @NarenMurali i can't use ngModel because im using reactiveForms with FormGroup and formControl – IKERAGI Commented Mar 16 at 14:58
Add a comment  | 

1 Answer 1

Reset to default 1

formControlName and other 'FormControl'-based directives (ngModel and formControl) need ControlValueAccessor to reside on the same node for proper state synchronization between the model and the view.

In your case, since the element comes from a library, you can't force it to provide NG_VALUE_ACCESSOR token which is required by the formControlName to resolve a ControlValueAccessor, so you can define a wrapper component that Implements ControlValueAccessor and wraps mac-select element, then you can use the wrapper in the template as follows:

@Component({
  selector:'app-wrapper',
  providers: [{
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(() => AppWrapperComponent ),
    multi: true,
  }],
  template:`
   <mac-select
    (click)="changePattern(form2.get('doc')?.value)"
    [items]="documents"
    [placeholder]="'Comun.TipoAcceso1.PlaceHolderSelect' | translate">
   
   </mac-select>
  `
 })
 export class AppWrapperComponent implements ControlValueAccessor {
   // Implement ControlValueAccessor methods.
}

Now you can use app-wrapper in your template:

<app-wrapper formControlName="doc_dni"></app-wrapper>

Alternatively, if you don't want to create another component to wrap it, you can define a directive that can be automatically attached to mac-select element if it's used as a part of a form (see the selector):

@Directive({
 selector: 'mac-select[formControlName],mac-select[formControl],mac-select[ngModel]',
 providers: [{
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => MacSelectValueAccessor ),
  multi: true
 }]
})
export class MacSelectValueAccessor implements ControlValueAccessor {
   // Implement ControlValueAccessor methods.
}

This way wherever you use mac-select as a part of a form, the FormControl-based directives will find a ControlValueAccessor resides on the same node.

本文标签: htmlType Error dirvalueAccessorregisterOnTouched is not a functionStack Overflow