Angular 2: Get Values of Multiple Checked Checkboxes - json

My problem is really simple: I have a list of checkboxes like this:
<div class="form-group">
<label for="options">Options :</label>
<label *ngFor="#option of options" class="form-control">
<input type="checkbox" name="options" value="option" /> {{option}}
</label>
</div>
And I would like to send an array of the selected options, something like:
[option1, option5, option8] if options 1, 5 and 8 are selected. This array is part of a JSON that I would like to send via an HTTP PUT request.
Thanks for your help!

Here's a simple way using ngModel (final Angular 2)
<!-- my.component.html -->
<div class="form-group">
<label for="options">Options:</label>
<div *ngFor="let option of options">
<label>
<input type="checkbox"
name="options"
value="{{option.value}}"
[(ngModel)]="option.checked"/>
{{option.name}}
</label>
</div>
</div>
// my.component.ts
#Component({ moduleId:module.id, templateUrl:'my.component.html'})
export class MyComponent {
options = [
{name:'OptionA', value:'1', checked:true},
{name:'OptionB', value:'2', checked:false},
{name:'OptionC', value:'3', checked:true}
]
get selectedOptions() { // right now: ['1','3']
return this.options
.filter(opt => opt.checked)
.map(opt => opt.value)
}
}

I have find a solution thanks to Gunter! Here is my whole code if it could help anyone:
<div class="form-group">
<label for="options">Options :</label>
<div *ngFor="#option of options; #i = index">
<label>
<input type="checkbox"
name="options"
value="{{option}}"
[checked]="options.indexOf(option) >= 0"
(change)="updateCheckedOptions(option, $event)"/>
{{option}}
</label>
</div>
</div>
Here are the 3 objects I'm using:
options = ['OptionA', 'OptionB', 'OptionC'];
optionsMap = {
OptionA: false,
OptionB: false,
OptionC: false,
};
optionsChecked = [];
And there are 3 useful methods:
1. To initiate optionsMap:
initOptionsMap() {
for (var x = 0; x<this.order.options.length; x++) {
this.optionsMap[this.options[x]] = true;
}
}
2. to update the optionsMap:
updateCheckedOptions(option, event) {
this.optionsMap[option] = event.target.checked;
}
3. to convert optionsMap into optionsChecked and store it in options before sending the POST request:
updateOptions() {
for(var x in this.optionsMap) {
if(this.optionsMap[x]) {
this.optionsChecked.push(x);
}
}
this.options = this.optionsChecked;
this.optionsChecked = [];
}

create a list like :-
this.xyzlist = [
{
id: 1,
value: 'option1'
},
{
id: 2,
value: 'option2'
}
];
Html :-
<div class="checkbox" *ngFor="let list of xyzlist">
<label>
<input formControlName="interestSectors" type="checkbox" value="{{list.id}}" (change)="onCheckboxChange(list,$event)">{{list.value}}</label>
</div>
then in it's component ts :-
onCheckboxChange(option, event) {
if(event.target.checked) {
this.checkedList.push(option.id);
} else {
for(var i=0 ; i < this.xyzlist.length; i++) {
if(this.checkedList[i] == option.id) {
this.checkedList.splice(i,1);
}
}
}
console.log(this.checkedList);
}

<input type="checkbox" name="options" value="option" (change)="updateChecked(option, $event)" />
export class MyComponent {
checked: boolean[] = [];
updateChecked(option, event) {
this.checked[option]=event; // or `event.target.value` not sure what this event looks like
}
}

I have encountered the same problem and now I have an answer I like more (may be you too). I have bounded each checkbox to an array index.
First I defined an Object like this:
SelectionStatusOfMutants: any = {};
Then the checkboxes are like this:
<input *ngFor="let Mutant of Mutants" type="checkbox"
[(ngModel)]="SelectionStatusOfMutants[Mutant.Id]" [value]="Mutant.Id" />
As you know objects in JS are arrays with arbitrary indices. So the result are being fetched so simple:
Count selected ones like this:
let count = 0;
Object.keys(SelectionStatusOfMutants).forEach((item, index) => {
if (SelectionStatusOfMutants[item])
count++;
});
And similar to that fetch selected ones like this:
let selecteds = Object.keys(SelectionStatusOfMutants).filter((item, index) => {
return SelectionStatusOfMutants[item];
});
You see?! Very simple very beautiful. TG.

Here's a solution without map, 'checked' properties and FormControl.
app.component.html:
<div *ngFor="let item of options">
<input type="checkbox"
(change)="onChange($event.target.checked, item)"
[checked]="checked(item)"
>
{{item}}
</div>
app.component.ts:
options = ["1", "2", "3", "4", "5"]
selected = ["1", "2", "5"]
// check if the item are selected
checked(item){
if(this.selected.indexOf(item) != -1){
return true;
}
}
// when checkbox change, add/remove the item from the array
onChange(checked, item){
if(checked){
this.selected.push(item);
} else {
this.selected.splice(this.selected.indexOf(item), 1)
}
}
DEMO

I hope this would help someone who has the same problem.
templet.html
<form [formGroup] = "myForm" (ngSubmit) = "confirmFlights(myForm.value)">
<ng-template ngFor [ngForOf]="flightList" let-flight let-i="index" >
<input type="checkbox" [value]="flight.id" formControlName="flightid"
(change)="flightids[i]=[$event.target.checked,$event.target.getAttribute('value')]" >
</ng-template>
</form>
component.ts
flightids array will have another arrays like this
[ [ true, 'id_1'], [ false, 'id_2'], [ true, 'id_3']...]
here true means user checked it, false means user checked then unchecked it.
The items that user have never checked will not be inserted to the array.
flightids = [];
confirmFlights(value){
//console.log(this.flightids);
let confirmList = [];
this.flightids.forEach(id => {
if(id[0]) // here, true means that user checked the item
confirmList.push(this.flightList.find(x => x.id === id[1]));
});
//console.log(confirmList);
}

In Angular 2+ to 9 using Typescript
Source Link
we can use an object to bind multiple Checkbox
checkboxesDataList = [
{
id: 'C001',
label: 'Photography',
isChecked: true
},
{
id: 'C002',
label: 'Writing',
isChecked: true
},
{
id: 'C003',
label: 'Painting',
isChecked: true
},
{
id: 'C004',
label: 'Knitting',
isChecked: false
},
{
id: 'C004',
label: 'Dancing',
isChecked: false
},
{
id: 'C005',
label: 'Gardening',
isChecked: true
},
{
id: 'C006',
label: 'Drawing',
isChecked: true
},
{
id: 'C007',
label: 'Gyming',
isChecked: false
},
{
id: 'C008',
label: 'Cooking',
isChecked: true
},
{
id: 'C009',
label: 'Scrapbooking',
isChecked: false
},
{
id: 'C010',
label: 'Origami',
isChecked: false
}
]
In HTML Template use
<ul class="checkbox-items">
<li *ngFor="let item of checkboxesDataList">
<input type="checkbox" [(ngModel)]="item.isChecked" (change)="changeSelection()">{{item.label}}
</li>
</ul>
To get selected checkboxes, add the following method in class
// Selected item
fetchSelectedItems() {
this.selectedItemsList = this.checkboxesDataList.filter((value, index) => {
return value.isChecked
});
}
// IDs of selected item
fetchCheckedIDs() {
this.checkedIDs = []
this.checkboxesDataList.forEach((value, index) => {
if (value.isChecked) {
this.checkedIDs.push(value.id);
}
});
}

I have just simplified little bit for those whose are using list of
value Object.
XYZ.Comonent.html
<div class="form-group">
<label for="options">Options :</label>
<div *ngFor="let option of xyzlist">
<label>
<input type="checkbox"
name="options"
value="{{option.Id}}"
(change)="onClicked(option, $event)"/>
{{option.Id}}-- {{option.checked}}
</label>
</div>
<button type="submit">Submit</button>
</div>
** XYZ.Component.ts**.
create a list -- xyzlist.
assign values, I am passing values from Java in this list.
Values are Int-Id, boolean -checked (Can Pass in Component.ts).
Now to get value in Componenet.ts.
xyzlist;//Just created a list
onClicked(option, event) {
console.log("event " + this.xyzlist.length);
console.log("event checked" + event.target.checked);
console.log("event checked" + event.target.value);
for (var i = 0; i < this.xyzlist.length; i++) {
console.log("test --- " + this.xyzlist[i].Id;
if (this.xyzlist[i].Id == event.target.value) {
this.xyzlist[i].checked = event.target.checked;
}
console.log("after update of checkbox" + this.xyzlist[i].checked);
}

I just faced this issue, and decided to make everything work with as less variables as i can, to keep workspace clean. Here is example of my code
<input type="checkbox" (change)="changeModel($event, modelArr, option.value)" [checked]="modelArr.includes(option.value)" />
Method, which called on change is pushing value in model, or removing it.
public changeModel(ev, list, val) {
if (ev.target.checked) {
list.push(val);
} else {
let i = list.indexOf(val);
list.splice(i, 1);
}
}

#ccwasden solution above works for me with a small change, each checkbox must have a unique name otherwise binding wont works
<div class="form-group">
<label for="options">Options:</label>
<div *ngFor="let option of options; let i = index">
<label>
<input type="checkbox"
name="options_{{i}}"
value="{{option.value}}"
[(ngModel)]="option.checked"/>
{{option.name}}
</label>
</div>
</div>
// my.component.ts
#Component({ moduleId:module.id, templateUrl:'my.component.html'})
export class MyComponent {
options = [
{name:'OptionA', value:'1', checked:true},
{name:'OptionB', value:'2', checked:false},
{name:'OptionC', value:'3', checked:true}
]
get selectedOptions() { // right now: ['1','3']
return this.options
.filter(opt => opt.checked)
.map(opt => opt.value)
}
}
and also make sur to import FormsModule in your main module
import { FormsModule } from '#angular/forms';
imports: [
FormsModule
],

Since I spent a long time solving a similar problem, I'm answering to share my experience.
My problem was the same, to know, getting many checkboxes value after a specified event has been triggered.
I tried a lot of solutions but for me the sexiest is using ViewChildren.
import { ViewChildren, QueryList } from '#angular/core';
/** Get handle on cmp tags in the template */
#ViewChildren('cmp') components: QueryList<any>;
ngAfterViewInit(){
// print array of CustomComponent objects
console.log(this.components.toArray());
}
Found here: https://stackoverflow.com/a/40165639/4775727
Potential other solutions for ref, there are a lot of similar topic, none of them purpose this solution...:
Angular 6: How to build a simple multiple checkbox to be checked/unchecked by the user?
Angular 6 How To Get Values From Multiple Checkboxes and Send in From
Angular how to get the multiple checkbox value?
Angular 2: Get Values of Multiple Checked Checkboxes
https://medium.com/#vladguleaev/reusable-angular-create-multiple-checkbox-group-component-84f0e4727677
https://netbasal.com/handling-multiple-checkboxes-in-angular-forms-57eb8e846d21
https://medium.com/#shlomiassaf/the-angular-template-variable-you-are-missing-return-of-the-var-6b573ec9fdc
https://www.bennadel.com/blog/3205-using-form-controls-without-formsmodule-or-ngmodel-in-angular-2-4-1.htm
How to get checkbox value in angular 5 app
Angular 2: Get Values of Multiple Checked Checkboxes
Filter by checkbox in angular 5
How to access multiple checkbox values in Angular 4/5

Related

Input fields as lists in Angular

I want to take inputs from the user and append them to a list I have in my typescript. Here's what I have tried so far.
Here's the code:
<input type="text" id="course" name="course" class="form-control"[(ngModel)]="institutes.course">
institutes={course:''}
Use a function to add a new course and trigger it using a button.
app.component.html :
<!-- Input field -->
<input type="text" id="course" name="course" class="form-control" [(ngModel)]="newCourse">
<!-- Add button -->
<button (click)="addCourse()">Add</button>
app.component.ts :
newCourse : string = '';
allCourses : string[] = [];
// Function to add course
addCourse(){
this.allCourses.push(this.newCourse);
//Reset input
this.newCourse = '';
}
Demo : https://stackblitz.com/edit/angular-hzh42b
Write the following method in your component -
constructor(private url: string, private http: HttpClient) {}
posts: any;
createPost(input: HTMLInputElement) {
const post = { title: input.value };
this.posts.splice(0, 0, post);
input.value = "";
this.service.create(post).subscribe(
newPost => {
post.id = newPost;
},
(error: AppError) => {
this.posts.splice(0, 1);
if (error instanceof BadInput) {
// this.form.setErrors(error.originalError);
} else {
throw error;
}
}
);
}
Include this method in your service -
constructor(private url: string, private http: HttpClient) {}
create(resource) {
return this.http.post(this.url, JSON.stringify(resource)).pipe(
map(response => response),
catchError(this.handleError)
);
}
write the following code in your HTML -
<input
(keyup.enter)="createPost(title)"
#title
type="text"
class="form-control"
/>
You are good to go now!
The following code will help you to add a course into a list, which will be displayed in the web page.
.ts
courseList contains a list of all the added courses
course is the current course that you are adding.
addCourse is a method which will add a course into the list, and clear the course string.
public courseList = [];
public course;
addCourse() {
this.courseList.push(this.course);
console.log(this.courseList);
this.course = '';
}
.html
There is an input field which will take in course name.
And an add course button which will add the entered course name into the list and display the course list in the web page.
<ul>
<li *ngFor="let course of courseList">
{{course}}
</li>
</ul>
<input type="text" id="course" name="course" class="form-control" [(ngModel)]="course">
<button (click)="addCourse()">Add Course</button>

How to delete entire row of the table on click checkbox of that row in angular 7

I have a table whose data is coming from loop.Here when you press add button new similar row will be added at just bottom.Again when you press edit button all textbox will be enable(initially disable).Till now working fine.But when I check single checkbox or multiple checkbox and press delete button all the row based on checked checkbox will be delete/remove.Again when I click delete button without selecting any checkbox alert message should display and also when user selected all check boxes and tried to delete all the row an alert message should be there that 'at least one row should be there' and he cannot delete all rows unless any one row will be unchecked.I am new to angular can anyone please help me.Here is the code below https://stackblitz.com/edit/angular-wscsmy
app.component.html
<div class="container">
<h2>Basic Table</h2>
<p>The .table class adds basic styling (light padding and only horizontal dividers) to a table:</p>
<div><button (click)="enable()">Edit</button>
<button (click)="delete()">Delete</button> </div>
<table class="table border">
<tbody>
<tr *ngFor="let row of groups;let i = index" (click)="setClickedRow(i)" [class.active]="i == selectedRow">
<td> <input type="checkbox"></td>
<td> <input #focus [disabled]='toggleButton' type="text" value="{{row.name}}"> </td>
<td> <input [disabled]='toggleButton' type="text" value="{{row.items}}"> </td>
<td> <button (click)="addRow(i)">Add</button></td>
</tr>
</tbody>
</table>
</div>
app.component.ts
import { Component, ViewChild, ElementRef } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
selectedRow: Number;
#ViewChild('focus', { static: false }) input: ElementRef;
public toggleButton: boolean = true;
ngOnInit() {
}
groups = [
{
"name": "pencils",
"items": "red pencil"
},
{
"name": "rubbers",
"items": "big rubber"
},
{
"name": "rubbers1",
"items": "big rubber1"
},
];
addRow(index): void {
var currentElement = this.groups[index];
this.groups.splice(index, 0, currentElement);
}
enable() {
this.toggleButton = false
setTimeout(() => { // this will make the execution after the above boolean has changed
this.input.nativeElement.focus();
this.selectedRow = 0;
}, 0);
}
delete(){
alert('hello');
}
setClickedRow(index) {
this.selectedRow = index;
}
}
You have to create an array to keep track of the state of each checkbox. And update it every time a checkbox is checked or unchecked.
Template:
<td>
<input type="checkbox" (click)="toggleSelection($event, i)" [checked]="checkboxes[i]">
</td>
Component:
checkboxes: boolean[];
ngOnInit() {
this.checkboxes = new Array(this.groups.length);
this.checkboxes.fill(false);
}
toggleSelection(event, i) {
this.checkboxes[i] = event.target.checked;
}
Also, add another checkbox entry to the array whenever a new row is added.
addRow(index): void {
// Other code.
this.checkboxes.splice(index, 0, false);
}
You can use Array.splice() to delete elements from an array.
Array.some() can be used to check if at least one checkbox is selected, and Array.every() can be used to check if all the checkboxes are selected.
delete() {
var atleastOneSelected = this.checkboxes.some(checkbox => checkbox === true);
var allSelected = this.checkboxes.every(checkbox => checkbox === true);
if (!atleastOneSelected) {
alert("No rows selected.");
return;
}
if (allSelected) {
alert("At least one row should be present.");
return;
}
// Iterating in reverse to avoid index conflicts by in-place deletion.
for (let i = this.checkboxes.length-1; i >= 0; i--) {
// If selected, then delete that row.
if (this.checkboxes[i]) {
this.groups.splice(i, 1);
}
}
// Remove entries from checkboxes array.
this.checkboxes = this.checkboxes.filter(checkbox => checkbox === false);
}
Live demo on StackBlitz: https://stackblitz.com/edit/angular-abhkyk
Use a helper array, where you store all the checked checkboxes. Before deletion, check that at least one value is present.
I choose to store the indexes of the items to the helper array, and based on that, delete from the original array. So perhaps something like this:
toBeDeleted = [];
// called when button is clicked
delete() {
if (!this.toBeDeleted.length) {
alert('Choose at least one!');
} else if (this.toBeDeleted.length === this.groups.length) {
alert('You cannot delete all rows')
}
else {
this.groups = this.groups.filter((currentValue, index, arr) => !this.toBeDeleted.includes(index));
}
// reset the array
this.toBeDeleted = [];
}
remove(event, index) {
// check if checkbox is checked, if so, push to array, else delete from array
if (event.target.checked) {
this.toBeDeleted.push(index)
} else {
const idx = this.toBeDeleted.indexOf(index);
this.toBeDeleted.splice(idx, 1)
}
}
Then in your template, when user clicks on checkbox, call remove() and pass the $event and index of item:
<td> <input type="checkbox" (click)="remove($event, i)"></td>
STACKBLITZ

Formgroup binding in select boxes with Angular

I have a nested JSON array which i have to iterate to HTML using formgroup or formarray. This response is to be iterated into dynamically created select boxes depending on the length of array.
The JSON response coming in is:
var result = [{
id: 1,
options: [
{ option: 'Ram', toBeSelected: false },
{ option: 'Ravi', toBeSelected: true }
]
},
{
id: 2,
options: [
{ option: 'Pooja', toBeSelected: false },
{ option: 'Prakash', toBeSelected: false }
]
}
]
I have to iterate this into HTML in such a way that if any of these options have toBeSelected as true, that option should be preselected in HTML and if not, placeholder text can be shown.
According to the JSON in question, you can make it like:
ngOnInit() {
this.form = this._FormBuilder.group({
selections: this._FormBuilder.array([])
});
// the api call should be made here
this.jsonResponse.map(item => {
const opts = item.options.filter(o => {
return o.toBeSelected
});
if (opts.length) {
this.addSelections(opts[0].option);
} else {
this.addSelections();
}
});
}
get selections() {
return this.form.get('selections') as FormArray
}
addSelections(value?: string) {
this.selections.push(
this._FormBuilder.control((value ? value : ''))
);
}
Live view here.
Stackblitz link: https://stackblitz.com/edit/dynamic-form-binding-kx7nqf
Something along the lines of this?
<div *ngFor="let result of results">
<p>ID - {{ result.id }}</p>
<div *ngFor="let option of result.options">
<input
type="checkbox"
[checked]="option.toBeSelected">
{{ option.option }}
</div>
</div>
This isn't an example of FormGroup though but should help you understand how it can be done.
Sample StackBlitz

Angular 2 Dynamically generated form with multiple checkbox not working

I am dynamically generating HTML Form based on a JSON. I am using the official example provided here: https://angular.io/guide/dynamic-form
I am trying to extend this example to have other controls in my dynamic form (textarea, radio button, checkbox, etc.). I have been able to achieve all controls, except for checkbox. Though the checkbox is visible on the screen, the value is not captured in its enclosing form.
My Checkbox definition goes like this:
import { QuestionBase } from './question-base-model';
export interface Values{
label: string;
value: string;
isChecked: boolean;
}
export class CheckBoxQuestion extends QuestionBase<boolean> {
controlType = 'checkbox';
options: Values[] = [];
constructor(options: {} = {}) {
super(options);
this.options = options['options'] || [];
}
}
My JSON for checkbox is like this:
{
key: 'sideDish',
label: 'Side dish',
type: 'checkbox',
order: 10,
name: 'sides',
options: [
{value: 'fries', isChecked: true, label: 'French Fries'},
{value: 'cheese', isChecked: false, label: 'Cheese'},
{value: 'sauce', isChecked: true, label: 'Tomato Sauce'}
]
}
And my Dynamic HTML template is as below:
<div [formGroup]="form" >
<label [attr.for]="question.key">{{question.label}}</label>
<div [ngSwitch]="question.controlType">
<!-- Checkbox -->
<div *ngSwitchCase="'checkbox'">
<span *ngFor="let opt of question.options; let i = index">
<input type="checkbox"
[formControlName]="question.key"
[id]="i+'_'+question.key"
[value]="opt.value">
<label [attr.for]="i+'_'+question.key">{{opt.label}}</label>
</span>
</div>
</div>
The FormControl code goes like this (no edits made here from the original example):
toFormGroup(questions: QuestionBase<any>[] ) {
let group: any = {};
questions.forEach(question => {
let validatorsArray = [];
if(question.required) validatorsArray.push(Validators.required);
group[question.key] = validatorsArray.length > 0 ? new FormControl(question.value || '', Validators.compose(validatorsArray)) : new FormControl(question.value || '');
});
return new FormGroup(group);
This method is consumed in the init function:
ngOnInit() {
this.form = this.qcs.toFormGroup(this.questions);
}
When I hit on Submit button, I am printing the "form.value". Rest all the controls prints with the value I have set in the form. But, an empty string as value for this checkbox. What am I doing wrong?
Thanks in advance!

List of dynamic checkbox in Angular and JSON API

I'm having trouble rendering dynamic checkboxes with JSON API response.
This 2 ng-repeats:
Bringing the listing of categories in BD, and;
ng-model with the selected category listing.
Below my HTML code;
<ul class="list-group">
<li class="list-group-item" ng-repeat="cats in categorias">
<div class="checkbox"><label><input type="checkbox" ng-model="checkbox[item.cats]"><span class="checkbox-material"><span class="check"></span></span></label> {{cats.name}}</div>
</li>
</ul>
JSON/API response (1)
[
{"id":"1","id_module":"1","name":"Esportes"},
{"id":"2","id_module":"1","name":"Entretenimento"},
{"id":"3","id_module":"1","name":"Terror"},
{"id":"4","id_module":"1","name":"Drama"}
]
JSON response (2)
{cats":["1","2"]}
I would like that the checkbox stay checked with the response.
Does anyone have any idea?
Here you have working fiddle, check it
jsfiddle.net/b895j3ay
var app = angular.module("Application", [])
app.controller('Ctrl', function($scope) {
$scope.roles = [{
id: 1,
text: 'guest'
}, {
id: 2,
text: 'user'
}, {
id: 3,
text: 'customer'
}, {
id: 4,
text: 'admin'
}];
$scope.isChecked = function(id, matches) {
var isChecked = false;
angular.forEach(matches, function(match) {
if (match === id) {
isChecked = true;
}
});
return isChecked;
}
$scope.user = {
roles: [2, 4, 3]
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.21/angular.min.js"></script>
<div ng-app="Application">
<div ng-controller="Ctrl">
<label ng-repeat="role in roles">
<input type="checkbox" ng-model="user.roles" checklist-value="role.id" ng-checked="isChecked(role.id,user.roles)">{{role.text}}
</label>
</div>
</div>
</div>