1

I mean I have an order page that has a dynamic order items collection . I want to require the user to have atleast one item in that array. I understand simple usage of a custom validator but in this case I am not validating a single control but an array. How do I say 'If there are no values in the array then give error' ?

createFormGroup(order: Order): FormGroup {
const group = this.fb.group({
  id: [order.id],
  isItPurchase: [order.isItPurchase],
  orderItems: this.fb.array([])
});

order.orderItems.forEach(x => {
  var formArray = group.controls.orderItems as FormArray;
  formArray.push(this.createOrderItem(x));
});

    return group;
  }

 
 createOrderItem(item: OrderItem): FormGroup {
    const formGroup = this.fb.group({
      id: [item.id],
      name: [item.name, Validators.required],
      unitPrice: [item.unitPrice, Validators.required],
      units: [item.units, Validators.required]
    });

    return formGroup;
  }

for a simple case I would do something like

      // xxxValidator(control: AbstractControl): { [key: string]: boolean } | null {
  //   if (control.value === 'xxx') {
  //     return { 'xxxValidator': true }
  //   }
  //   return null;
  // };

EDIT 1:

I am closer. I identify when the error exist. But my template is wrong. How do I see the error in the template?

createFormGroup(order: Order): FormGroup {
    const group = this.fb.group({
      id: [order.id],
      isItPurchase: [order.isItPurchase],
      orderItems: this.fb.array([])
    },
      { validators: [this.testValidation1] }
      // { validators: [this.testValidation2] }
    );

    order.orderItems.forEach(x => {
      var formArray = group.controls.orderItems as FormArray;
      formArray.push(this.createOrderItem(x));
    });

    return group;
  }

  createOrderItem(item: OrderItem): FormGroup {
    const formGroup = this.fb.group({
      id: [item.id],
      name: [item.name, Validators.required],
      unitPrice: [item.unitPrice, Validators.required],
      units: [item.units, Validators.required]
    });

    return formGroup;
  }

  testValidation1(form: FormGroup) {
    if (form.value.orderItems.length === 0) {
      return { valOrderItems: false };
    }

    return null;
  }

    <div>
        <div *ngFor="let fg of orderItems.controls;  let i=index">
            <app-order-item-form [orderItemForm]="fg" (itemDeleted)="onItemDeleted(i)"></app-order-item-form>
        </div>
        <!-- <span *ngIf="orderForm.errors.valOrderItems"> Must be atleast one orderItem </span> -->
    </div>

2 Answers 2

1

Option 1

You can use the required validator to validate that the form has at least one element


const group = this.fb.group({
  id: [order.id],
  isItPurchase: [order.isItPurchase],
  orderItems: this.fb.array([], [Validators.required])
});

Now to get If the array has no values you can check if the required validator fails

const error = group.get('orderItems').hasError('required');  // True if form is empty

Option 2

Create a validator function

function formIsEmpty(control: FormArray) {
  if (control.controls.length === 0) {
    return { noValue: true}
  }
  return null;
}

And in your FormGroup you can use it like


const group = this.fb.group({
  id: [order.id],
  isItPurchase: [order.isItPurchase],
  orderItems: this.fb.array([], [formIsEmpty])
});

And get the error by

group.get('orderItems').hasError('noValue');
Sign up to request clarification or add additional context in comments.

Comments

1

Maybe you should get the FormArray controls by

   get itemsFormArray(): FormArray {
        return this.createFormGroup.get('orderItems') as FormArray;
    }

and then use it in your template, maybe maybe it doesn't work or not what you need but I hope it gives you the clue

  <mat-error *ngIf="itemsFormArray.hasError('required')">
                    // ERROR MESSAGE               
  </mat-error>

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.