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"