Angular 6: How to build a simple multiple checkbox to be checked/unchecked by the user?

Here is a working example, where you can observe that an additional 'checked' value is added to each country, and bound to the value of each checkbox with [(ngModel)].

Stackblitz live example

template:

<p>
Test checkboxes
</p>

<div *ngFor="let country of countries; let i = index;">
  <input type="checkbox" name="country{{country.id}}" [(ngModel)]="countries[i].checked">
  <label for="country{{country.id}}">{{country.name}}</label>
</div>

<button type="button" (click)="sendCheckedCountries()" *ngIf="countries">Click to send the selected countries (see your javascript console)</button>

<p *ngIf="!countries">loading countries, please wait a second...</p>
<p *ngIf="countries">Debug info : live value of the 'countries' array:</p>

<pre>{{ countries | json }}</pre>

component :

//...
export class AppComponent implements OnInit  {
  public countries: Country[];

  constructor(private countryService: CountryService) {}

  public ngOnInit(): void {
    // loading of countries, simulate some delay
    setTimeout(() => {
       this.countries = this.countryService.getCountries();
    }, 1000);
  }

  // this function does the job of sending the selected countried out the component
  public sendCheckedCountries(): void {
    const selectedCountries = this.countries.filter( (country) => country.checked );
    // you could use an EventEmitter and emit the selected values here, or send them to another API with some service

    console.log (selectedCountries);
  }
}

To use some proper TypeScript, I made an interface Country :

interface Country {
    id: number;
    name: string;
    checked?: boolean;
}

I hope you get the idea now.

Note : the checked value is not "automatically there" at the beginning, but it doesn't matter.

When not there, it is the same as undefined, and this will be treated as false both in the checkbox and in the function that reads which country is checked.

For the "sending value" part :

The button will output the selected value to the browser's console, with some filter similar to what @Eliseo's answer suggests (I just used full country objects instead of ids)

For "real usecase" situation, you could use Angular's EventEmitters and have your component "emit" the value to a parent component, or call some service function that will make a POST request of your values to another API.


Your countries like

{id: 1, name: 'Italia',checked:false},

Your html like

<div *ngFor="let country of countries">
  <input type="checkbox" [(ngModel)]="country.checked"/>
  <label>{{country.name}}</label>
</div>

You'll get an array like, e.g.

 [{id: 1, name: 'Italia',checked:false},{id: 2, name: 'Brasile',checked:tue}..]

you can do

result=this.countries.filter(x=>x.checked).map(x=>x.id)
//result becomes [2,...]

I had an error using [(ngModel)]

In case it serves anyone, I have solved the problem changing [(ngModel)] to:

[checked]="countries[i].checked" (change)="countries[i].checked= !countries[i].checked"

Tags:

Angular6