1

So I am getting the following error in unit testing a nested angular form:

 No value accessor for form control with path: 'address -> address1'

      at _throwError (../packages/forms/src/directives/shared.ts:140:9)
      at setUpControl (../packages/forms/src/directives/shared.ts:37:27)
      at FormGroupDirective.addControl (../packages/forms/src/directives/reactive_directives/form_group_directive.ts:132:5)
      at FormControlName._setUpControl (../packages/forms/src/directives/reactive_directives/form_control_name.ts:278:66)
      at FormControlName.ngOnChanges (../packages/forms/src/directives/reactive_directives/form_control_name.ts:207:28)

The form is defined as follows

ngOnInit() {
  this.form = this.fb.group({
    address: this.fb.group({
      address1: '',
      address2: '',
      ...
    })
  })
}

Template:

<form formGroup="form">
        <form formGroupName="address">
          <custom-text-input formGroupName="adress1" label="Address 1">
          </custom-text-input>
          <custom-text-input formGroupName="adress2" label="Address 1">
          </custom-text-input>
          <custom-text-input formGroupName="phone" label="Phone">
          </custom-text-input>
          <custom-text-input formGroupName="zipCode" label="Zip Code">
          </custom-text-input >
          <custom-text-input formGroupName="state" label="State">
          </custom-text-input >
        </form>
      </form>
2
  • Show us the template file. Commented Sep 6, 2019 at 3:00
  • added, custom text input has the CtonrolValueAccessor implemented. Commented Sep 7, 2019 at 0:20

2 Answers 2

2

I think you are missing an additional this.fb.group({}) when nesting form controls

this.form = this.fb.group({
   address: this.fb.group({
      address1: [''],
      address2: ['']
   })
})

Have a read from the official docs on Reactive Forms - Generating form controls


Also, formControlName only works with <input>, <select> and <textarea>. Do double check your template file if you had used formControlName on any other elements.

If you wish to use formControlName with another form control, you will have to create a custom form control using ControlValueAccessor class. See this alligator.io's article on creating custom form controls.


EDIT

Aside from formGroupName input binding, there's also formControlName input binding that's used for controls declared inside a FormGroup.

Taken from Angular's official docs, Associating the FormGroup model and view:

The formControlName input provided by the FormControlName directive binds each individual input to the form control defined in FormGroup. The form controls communicate with their respective elements. They also communicate changes to the form group instance, which provides the source of truth for the model value.

  this.form = this.fb.group({
    address: this.fb.group({
      address1: '',
      address2: '',
      ...
    })
  })

//is equal to

   this.form = new FormGroup({
      address: new FormGroup({
          address1: new FormControl(''),
          address2: new FormControl('') 
      })
   })

As you can see, address1 and address2 is not a new instance of form group. I think your code should work if you use formControlName instead of formGroupName.

<form [formGroup]="form">
    <form formGroupName="address">
        <custom-text-input formControlName="adress1" label="Address 1">
        </custom-text-input>
        <custom-text-input formControlName="adress2" label="Address 1">
        </custom-text-input>
        <custom-text-input formControlName="phone" label="Phone">
        </custom-text-input>
        <custom-text-input formControlName="zipCode" label="Zip Code">
        </custom-text-input>
        <custom-text-input formControlName="state" label="State">
        </custom-text-input>
    </form>
</form>
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks, that I'm already doing, to be clear the component is working fine, its just for unit test thats failing.
could you edit in your test suite, or at least the test case that's failing along with your beforeEach, afterEach, etc?
hi @user2167582, I have edited my answer, I think the structure of your form is still wrong, that's why it's still not working
0

The solution that I found was adding the custom component to the declarations array when configuring the TestBed module.

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [ CustomFormControlComponent],
      imports: [ FormsModule,
        RouterTestingModule,
        ReactiveFormsModule,
        HttpClientModule,
        CommonModule, ]
    })
    .compileComponents();
  });

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.