Angular reactive Form: 'Error: No value accessor for form control with'

104 Views Asked by At

I created a form that contains several FormGroup in a FormArray. The user can dynamically generate several FormGroup according to his needs I initiate a FormGroup in the code so that the user does not fall on an empty page

  ngOnInit(): void {
    this.buildOrderForm();
  }

  private buildOrderForm() {
    this.orderForm = this.formBuilder.group({
      message: [''],
      orders: this.formBuilder.array([this.createOrder()]) // this line initiates a first FormGroup
    });
  }

  private createOrder(): FormGroup {
    return this.formBuilder.group({
      produit: ['', Validators.required],
      document: ['', Validators.required],
      quantite: ['']
    });
  }

  protected addOrder(): void {
    this.ordersFormArray.push(this.createOrder()); 
  }

When I perform a unit test on this code that tests the creation of the component instance, I encounter the following error: Error: No value accessor for form control with path: 'orders -> 0 -> produit'

But when I remove the call from the createOrder method in the FormArray like this, the test proceeds correctly and the component instance is created

  private buildOrderForm() {
    this.orderForm = this.formBuilder.group({
      message: [''],
      orders: this.formBuilder.array([]) // suppres createOrder()
    });
  }

Here's the html template:

<form [formGroup]="orderForm" (ngSubmit)="onSendOrders()">
    <div class="container">
      <h4 class="container__title">{{ 'order.form.message.printout' | translate }}</h4>

      <!--Type de produit-->
      <div formArrayName="orders" ngDefaultControl>
        <div *ngFor="let order of ordersFormArray.controls; let i = index">
          <div [formGroupName]="i">

            <mat-form-field appearance="fill">
              <mat-label>{{
                'order.form.field.product' | translate
                }}</mat-label>
              <mat-select
                formControlName="produit"
                (selectionChange)="documentsChangeAction($event.value, i)"
              >

                <mat-option
                  id="{{ 'label-option' + i }}"
                  *ngFor="let product of productList"
                  [value]="product.label"
                >
                  {{ product.label }}
                </mat-option>
              </mat-select>
            </mat-form-field>
............................
</form>

How can I fix this error ? Thanks for help. Here's the complete code on this stackblitz :

EDIT : added full test code

import { NO_ERRORS_SCHEMA } from '@angular/core';
import { FormArray, ReactiveFormsModule } from '@angular/forms';
import {
  createComponentFactory,
  mockProvider,
  Spectator,
} from '@ngneat/spectator/jest';
import { TestHelperModule } from 'src/test/helpers/test-helper.module';
import { OrderFormComponent } from './order-form.component';
import { IDocumentProduct } from '../model/document-product.model';
import { ConfigService } from '@core/services/config.service';
import { OrderService } from '../service/order.service';
import { Observable, of } from 'rxjs';
import { MatInputModule } from '@angular/material/input';
import { MatIconModule } from '@angular/material/icon';

const productList: IDocumentProduct[] = [
  {
    id: '1',
    label: 'Tous',
    documents: [
      {
        id: '3',
        label: 'Sticker moto',
        qtteMax: 2,
      },
      {
        id: '2',
        label: 'Pochette assuré',
        qtteMax: 10,
      },
      {
        id: '5',
        label: 'Porte vignette',
        qtteMax: 20,
      },
      {
        id: '1',
        label: 'Carte verte',
        qtteMax: 20,
      },
      {
        id: '4',
        label: 'Enveloppe T',
        qtteMax: 20,
      },
    ],
  },
  {
    id: '2',
    label: 'Auto',
    documents: [
      {
        id: '18',
        label: "Convention d'assistance AUTO",
        qtteMax: 10,
      },
      {
        id: '14',
        label: 'Dépliant assuré AUTO',
        qtteMax: 10,
      },
      {
        id: '6',
        label: 'Dispositions générales AUTO',
        qtteMax: 10,
      },
    ],
  },
];

describe('OrderFormComponent', () => {
  let spectator: Spectator<OrderFormComponent>;

  const createComponent = createComponentFactory({
    component: OrderFormComponent,
    imports: [
      ReactiveFormsModule,
      TestHelperModule,
      MatIconModule,
      MatInputModule,
    ],
    mocks: [NavigationService, NotificationService],
    providers: [
      mockProvider(OrderService, {
        getAllProducts: (): Observable<IDocumentProduct[]> =>
          of(productList as IDocumentProduct[]),
      }),
      mockProvider(ContextSessionService, {
        activeProfile: (): Observable<IApporteur | IVendeur | null> =>
          of({ protocoleSigne: true } as IApporteur),
        activeSubtitutionProfile: (): Observable<
          IApporteur | IVendeur | null
        > => of(null),
      }),
      mockProvider(ConfigService, {
        getValue: jest.fn(() => 'fakeurlwebadelia.com/apporteur'),
      }),
    ],
  });

  beforeEach(
    () =>
      (spectator = createComponent({
        props: { productList: productList },
      }))
  );

  it('should create', () => {
    expect(spectator.component).toBeInstanceOf(OrderFormComponent);
  });
});

0

There are 0 best solutions below