1

I have a form with some types of inputs. There is a mistake in validation in the checkbox type. See the stackblitz demo.

First, check the first item. Then check the second one and then uncheck the first one. It shows error message!

Html:

<form name="form" (ngSubmit)="addBookletForm.valid && addBooklet()" #addBookletForm="ngForm" novalidate >
  <label *ngFor="let option of levelCheckboxes">
    <div *ngIf="( booklet_level.touched || addBookletForm.submitted) && booklet_level.invalid && booklet_level.errors.required">
        <div class="saz-alert saz-alert-red saz-alert-small saz-color-red" *ngIf="booklet_level.errors.required">
          This is required!
        </div>
    </div>
    <input name="booklet_level" #booklet_level="ngModel" required value="{{option.value}}" [(ngModel)]="option.checked" type="checkbox">
    {{option.name}}

  </label>
</form>

Typescript:

levelCheckboxes = [
    { name:'one', value:'1', checked:false },
    { name:'two', value:'2', checked:false },
    { name:'three', value:'3', checked:false }
]
2
  • 1
    Apparently, all of the radio buttons are sharing the same model Object as it's essentially a JS Object which is passed by reference. Hence the behavior. Commented Jul 21, 2019 at 13:28
  • @SiddAjmera Any idea how to fix it? Commented Jul 21, 2019 at 13:56

2 Answers 2

1

I have understood your requirement. Your html can be modified as

<hello name="{{ name }}"></hello>
<p>
  Start editing to see some magic happen :)
</p>

<div *ngIf="isChecked == false">
  Atleast one checkbox should be checked!
</div>
<form name="form" (ngSubmit)="addBookletForm.valid && addBooklet()" #addBookletForm="ngForm" novalidate >
  <label *ngFor="let option of levelCheckboxes">
     <input name="booklet_level" [(ngModel)]="option.checked" type="checkbox" (change)="isCheckBoxChecked()">
    {{option.name}}
  </label>
</form>

And in your .ts file you can have a function called isCheckBoxChecked() to display the respective validation error,

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  isChecked: boolean = false;
  name = 'Angular';
  levelCheckboxes = [
        { name:'one', value:'1', checked:false },
        { name:'two', value:'2', checked:false },
        { name:'three', value:'3', checked:false }
    ]

  isCheckBoxChecked(){
    this.isChecked = false;
    this.levelCheckboxes.forEach(checkbox => {
      if(checkbox.checked){
        this.isChecked = true;
      }
    })
  }
}

Hope it helps!

Sign up to request clarification or add additional context in comments.

6 Comments

No, at least one checkbox must be checked.
@Vahid Thanks for the clarification ! let me correct the condition and will update the answer
You can test your solution in stackblitz (link in the question)
@Vahid I have made changes to the code and it is working based upon your requirements! Hope it helps
It seems this is the only way to check it manually. But still wondering why this happens. Btw, thanks.
|
1

The issue is that you are using the same value for the name attribute on every checkbox input, booklet_level. Because you are using an ngForm all the NgModels get merged to one. So, you get very weird and unexpected behaviour.

If you change the name to something like this, it will work:

<input name="booklet_level_{{option.name}}" required 
       type="checkbox" value="{{option.value}}" 
       [(ngModel)]="option.checked" #booklet_level="ngModel">

3 Comments

In this case, all the checkboxes must be checked.
@VahidNajafi well you are putting a required attribute on every checkbox. If you just want at least one to be selected you should not use the required attribute at all
In that case user can skip checkboxes without any selection. Would you please see the stackblitz demo provided in the question?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.