Search code examples
angularcheckboxangular-reactive-formsangular-forms

Angular Check checkboxes on load


need your help

I have an array of checkbox values

colors = ['Black', 'Red', 'White', 'Blue', 'Yellow', 'Grey'];

Implemented them in HTML

<div *ngFor="let color of colors; let i = index" class="checkbox">
        <label>
          <input type="checkbox" class="colors" [value]="color" (change)="addCheckboxData($event)" />
          {{ color }}
        </label>
      </div>

So it looks like this: enter image description here

I have an array of values that should be checked when I load the page

  checkedValues = ['Black', 'White', 'Grey'];

I added them to formarray

color: this._formBuilder.array(this.checkedValues),

It works and color formarray have values like in checkedValues array: enter image description here

But checkboxes are not checked so I want this values to be displayed as checked. How can I do this? Thank You


Solution

  • you need pass an array of booleans

    color: this._formBuilder.array(
                  this.colors.map(x=>this.checkedValues.indexOf(x)>=0)),
    

    And manage the form like

    <form [formGroup]="form">
        <input formControlName="name">
        <div formArrayName="color">
            <div *ngFor="let control of colorFormArray.controls;let i=index">
                <input type="checkbox" [formControlName]="i">{{colors[i]}}
          </div>
            </div>
    </form>
    <pre>
    {{form?.value|json}}
    </pre>
    

    Well, you see that "color" get as value an array of booleans, e.g. [true,false,true,false,false,true]

    And you want that color get an array with the colors, so the idea is has a formControl not a formArray and use [ngModel] and (ngModelChange). As we are using [ngModel] inside a FormGroup, we need use [ngModel]="{standalone:true}"

    See the form and the .html

    this.form2=this._formBuilder.group({
      name:[],
      color:[this.checkedValues] //<--see that is a simple FormControl
    })
    
    <form [formGroup]="form2">
            <div *ngFor="let col of colors;let i=index">
                <input type="checkbox" 
               [ngModel]="form2.get('color').value && form2.get('color').value.indexOf(col)>=0" 
               (ngModelChange)="colorChange($event,i)"
               [ngModelOptions]="{standalone:true}"
                     
          >{{colors[i]}}
            </div>
    </form>
    

    The [ngModel] is true or false according form2.get('color').value.indexOf

    The function colorChange received the value of the checkbox and an index

      colorChange(checked:boolean,index:number)
      {
        const checkedColors=this.form2.get('color').value || [] //the actual value of the formControl
                                                                //if is null an empty array
        const color=this.colors[index];  //the color selected
    
        ///if is checked and is not in the array
        if (checked && checkedColors.indexOf(color)<0)
        {
          //concatenate to the value the new color
          //and sort the result array 
    
          const orderColors=[...checkedColors,color]
                      .sort((a,b)=>this.colors.indexOf(a)-this.colors.indexOf(b))
    
          //make a setValue
          this.form2.get('color').setValue(orderColors)
        }
    
        //if not checked
    
        if (!checked)
          this.form2.get('color').setValue(checkedColors.filter(x=>x!=color))
    
      }
    

    In the stackblitz you has the two aproach

    NOTE: In this secod aproach we can make that if there are no color select, the value of the control becomes null. This allow us use a Validators.required, e.g. The only is change the function colorChange

      colorChange(checked:boolean,index:number)
      {
            ...
    
        if (!checked)
        {
          const result=checkedColors.filter(x=>x!=color)
          this.form2.get('color').setValue(result.length>0?result:null)
        }
    
      }