1

I am generating check boxes dynamically using FormArray & Reactive Forms Module.

The thing I need here is I want to disable rest check boxes if user selects any 2 check boxes. And if he deselects any 1 the again allow him to select from others. When 2 selection is done then all rest disable.

Below is HTML PART

    <form [formGroup]="userForm" (ngSubmit)="onFormSubmit()">
    <label>
      <b>Time Out Period :</b>
    </label>
    <div class="input-group">
      <input type="text" class="form-control" maxlength="2" formControlName="tbl_config_TimeoutPeriod">
    </div>
    <div *ngIf="tbl_config_TimeoutPeriod.invalid && tbl_config_TimeoutPeriod.touched">
      <span style="color:red;margin-top:3px">Time Out Period field is mandatory..!</span>
    </div>
    <br>
    <div formArrayName="users">
      <div *ngFor="let user of users.controls; index as idx">
        <input [formControlName]="idx" type="checkbox"   >
        <button (click)="deleteUserField(idx)">Delete</button>
      </div>
    </div>
    <br>
    <button type="submit" [disabled]="!userForm.valid" class="btn btn-primary">Save Changes</button>
    <button type="button" (click)="addUserField()">Add More User</button>
  </form>

Below is TS PART

  userForm = new FormGroup({
        tbl_config_TimeoutPeriod: new FormControl('', Validators.required),
        users: new FormArray([
          new FormControl('', Validators.required)
        ])
      });

 get users(): FormArray { return this.userForm.get('users') as FormArray; }
  get tbl_config_TimeoutPeriod() { return this.userForm.get('tbl_config_TimeoutPeriod'); }

  onFormSubmit() {
    console.log(this.userForm.value); // Gives Complete form data
  }

  addUserField() {
      this.users.push(new FormControl(''));
  }

  deleteUserField(index: number) {
    this.users.removeAt(index);
  }

1 Answer 1

1

You could change your input like so:

    <input type="checkbox" 
        [disabled]="amountChecked==2&&!input.checked
            ?'disabled'
            :''" 
        (change)="handleCheck($event.target)" 
        #input>

...and add this to your component.ts:

amountChecked=0
handleCheck(ev){
  if(ev.target.checked==true){
    this.amountChecked++
  }else{
    this.amountChecked--
  }
}

also, change the deleteUserField() method:

deleteUserField(index: number,el:HTMLInputElement) {
  el.checked=false
  this.handleCheck(el)
  this.users.removeAt(index);
}

See proof of concept

  • amountChecked gets altered on any change on the checkbox value. It holds the value for how many checkboxes are checked.
  • [disabled] binds to a custom amount that you set (2 here), where if this value is reached, all non-checked checkboxes get disabled.
  • #input is a template reference variable, scoped to every single ngFor-loop, so always referencing the input itself. This is to avoid disabling the checked checkboxes.

Edit

As requested, I updated the link to the example, mergin all code from the question with my solution. additionally, I made some changes above and in the example for being able to delete inputs and handling state correctly.

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

14 Comments

i copied your code in a new project with my additions here
oops, sorry, wrong link, anyway, there was still a problem, so here is the working example. Before it wasn't handling the deletion of checkboxes. I will update my answer
hey, sorry, missed your comment. I think i missed the [formControlName]="idx" part. I'm not too familiar with reactive forms, but putting it in seems to do it
Hey, sorry, I'm at work, so I can't response usually. Anyway, look at this. that should re-enable the max-checked-logic. basically you cant use [disabled] binding, but have to use control.disable() or control.enable() If all is as you wish, I will update the answer in a few hours
No :) I meant check the solution in the link in my last comment, if it is what fulfills all needs i update. I think it should be good to go, but just to be sure you check it
|

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.