Code for select/unselect all checkboxes in an AngularJS Table - javascript

Iam completely confused at a point and need anyone's help here. Went through various examples but nothing could help.
I have a created dynamic table, added with checkboxes. Now whenever a row is selected its id will be bound to an array and it will be diplayed at the top of table.
What I need is:The code for functionality of select all check box. And whenever all the rows are selected by select all checkbox, its ids has to be displayed.
Below is the code for the table:
<table>
<thead>
<tr>
<th>
<input name="all"
type="checkbox"
ng-click="selectAll()" />
</th>
<th>ID</th>
<th>Date</th>
</tr>
</thead>
<tbody ng-repeat="x in cons">
<tr>
<td>
<input type="checkbox"
name="selectedids[]"
value="{{x.id}}"
ng-checked="idSelection.indexOf(x.id) > -1"
ng-click="toggleSelection(x.id, idSelection)"> </td>
<td>{{x.id}}</td>
<td>{{x.title}}</td>
</tr>
</tbody>
app.js:
$scope.idSelection = [];
$scope.toggleSelection = function toggleSelection(selectionName, listSelection) {
var idx = listSelection.indexOf(selectionName);
// is currently selected
if (idx > -1) {
listSelection.splice(idx, 1);
}
// is newly selected
else {
listSelection.push(selectionName);
}
};
//$scope.selectAll=function(){}
//Need code for this function to work
Here is a demo: http://plnkr.co/edit/m9eQeXRMwzRdfCUi5YpX?p=preview.
Will be grateful, if anyone can guide.

You need a variable to keep track of whether 'All' is currently active or not. If not, we create a new array of all item id's using the array map function, and pass this to idSelection. If allSelected is currently active, we pass an empty array to idSelection
$scope.allSelected = false;
$scope.selectAll = function() {
$scope.allSelected = !$scope.allSelected;
if($scope.allSelected) {
$scope.idSelection = $scope.cons.map(function(item) {
return item.id;
});
} else {
$scope.idSelection = [];
}
}

Related

How to get the value of checkboxes that are checked by using the form object in Javascript

I am a beginner at Javascript and I have a problem with my Javascript form objects. How do I loop through the entire form object select only the elements that are checked by the user. So far I have tried the following:
//Gets the selected checkbox values:
function getCbValues() {
var chkMouse = document.getElementById("chkMouse");
var chkKeyboard = document.getElementById("chkKeyboard");
var chkDVD = document.getElementById("chkDVD");
var chkSound = document.getElementById("chkSound");
var myFormElem = myForm.elements;
for (var i = 0; i < myFormElem.length; i++) {
if (myFormElem[i].type == "checkbox") {
if (myFormElem.checked == true) {
if (myFormElem[i].elementId == chkMouse) {
alert("This is the Mouse");
}
if (myFormElem[i].elementId == chkKeyboard) {
alert("This is the Keyboard");
}
if (myFormElem[i].elementId == chkDVD) {
alert("This is the DVD");
}
if (myFormElem[i].elementId == chkSound) {
alert("This is the Sound");
}
} else {
alert("Nothing");
}
}
}
}
I have declared all the var for all the different checkbox Id's. Here is the html:
<form action="" name="form1">
<!--Checkbox table-->
<table>
<!--Select Add on Item's-->
<tr class="firstHeader">
<th colspan="3">
<h3>Select Add On Items (Optional):</h3>
</th>
</tr>
<tr>
<th colspan="2">Add On Items</th>
</tr>
<tr>
<td><label>Mouse</label>
<td><input type="checkbox" name="chkMouse" value="Mouse" id="chkMouse" price="31" /></td>
</tr>
<tr>
<td><label>Keyboard</label></td>
<td><input type="checkbox" name="chkKeyboard" value="Keyboard" id="chkKeyboard" price="42" /></td>
</tr>
<tr>
<td><label>DVD Rome Drive</label></td>
<td><input type="checkbox" name="chkDVD" value="DVD Rome Drive" id="chkDVD" price="56" /></td>
</tr>
<tr>
<td><label>Sound Card</label></td>
<td><input type="checkbox" name="chkSound" value="Sound Card" id="chkSound" price="83" /></td>
</tr>
</table>
As you can see I have put the form into a table. But my issue is that whenever I run the Javascript the returned value is always null or undefined. My question is that how can I make a form object in Javascript loop over all these elements and in the end only return the values of the checkboxes that are checked. Can someone help me with this issue please. Thanks in advance !!
The reason you get nothing returned is because your getCbValues() function is not getting called anywhere in the code you have shown. Even if it was it would only show the current state as you haven't set up anything to respond to changes.
What I would do is set up event listeners to detect when a checkbox is checked and then do something with that information. You should do that outside of any function.
You can set an event listener like this:
var chkMouse = document.getElementById("chkMouse");
chkMouse.addEventListener('change', () => {
alert('this is the mouse')
})
Assuming you want to submit your form with the checked data you would probably add the item to an array that is then submitted as form data on submit.
Additionally you would want to check whether someone un-checks your item. You could do that like this:
chkMouse.addEventListener('change', () => {
if (chkMouse.checked) {
alert('mouse added')
} else {
alert('mouse removed')
}
})

Selecting specific value in row of the selected checkbox and checking for duplicates

I came across a problem whose solution has led me to post it here so others may make use of it or improvise better than me.
My Problem: I have a table of results with check boxes to select rows. The requirement was to know if I was selecting(using the checkboxes) the same set of one particular column value, if so I had to do something.
HTML code
Considering the below being my html code for the dynamic table(CFML). The tag has to be inside a loop to dynamically create the table content.
<table class="fixedTable">
<thead class="containerbg">
<tr class="listingheader">
<td>StagingID</td>
<td>BatchID</td>
<td>AuditID</td>
<td>Action</td>
<td>File Name</td>
<td>Card No</td>
<td>Card No</td>
</tr>
</thead>
<tbody>
<tr class="cur_row" >
<td>#staging_id#</td>
<td>#batch_import_job_id#</td>
<td>#audit_Id#</td>
<td>#code#</td>
<td class="file_name">#source_filename#</td>
<td>#card_number#</td>
<td class="tblResolve">
<input type="checkbox" class="checkBoxClass cb" name="resolveErrorsCheck" value="#row_no#">
</td>
</tr>
JS Code
//register the click event
$(document).ready(function() {
$(document).on('click', '.cb',enableDisableActions);
});
function enableDisableActions() {
var values = new Array();
$.each($("input[name='resolveErrorsCheck']:checked").closest('td').siblings('.file_name'),
function (){
values.push($(this).text());
});
const initial = values[0];
const result = values.filter(src => src != initial);
if(result.length){
//no duplicate file_name selected
//do something
}else{
//duplicate file_name selected
//do something
}
}

Angular 1: check all check boxes in a large ng-repeat

I have an table created using ng-repeat and there hundreds of rows, up to 600 or 700. Each row includes a checkbox and I have a "Check All" box at the top to check all the boxes in one go. However I'm running into browser performance issues, IE11 (the clients preferred choice) in particular becomes unresponsive. After several minutes all the checkboxes appear checked but you still can't scroll or do anything so it is effectively useless.
I have created a controller array and when the checkAll box is clicked it loops through the model (the one used in ng-repeat) and adds a value to the array. I presume it's this looping through the array that is causing the slow-down but I'm not sure. Pagination has been ruled out, they want all the rows on one page.
<table>
<tbody>
<tr>
<th>Table Header</th>
<th><input type="checkbox" id="checkAllCheckBox" ng-model="vm.allChecked" ng-change="vm.tickOrUntickAllCheckBoxes()" />
</tr>
<tr ng-repeat="payment in vm.payments>
<td>{{ payment.somePaymentValue }}</td>
<td>
<input type="checkbox" class="paymentsApprovalCheckbox"
ng-checked="vm.approvedPayments.indexOf(payment.payId) > - 1"
ng-value="payment.payId" ng-model="payment.approved"
ng-click="vm.handleCheckBoxClick(payment.payId)" />
</td>
</tr>
</tbody>
</table>
Here is the angular function that checks/unchecks all
vm.tickOrUntickAllCheckBoxes = function(){
if (vm.allChecked == false) {
vm.approvedPayments = [];
} else {
vm.payments.forEach(function(payment){
vm.approvedPayments.push(payment.payId);
});
}
};
Swapping out the angular vm.tickOrUntickAllCheckBoxes() function for a plain old javascript option makes the checkAll box work almost instantaneously in IE11 however I lose access to the checked payment.payId values. I wonder is there away for angular to get them? Here is the plain javascript checkAll() function:
<script>
function checkAll(x) {
var checkBoxes = document.getElementsByClassName('paymentsApprovalCheckbox');
for (var i = 0; i < checkBoxes.length ; i++) {
checkBoxes[i].checked = (x.checked == true);
}
}
</script>
Then I update the checkAll checkbox like this:
<input type="checkbox" id="checkAllCheckBox" ng-model="vm.allChecked" onclick="checkAll(this)" />
If you check one checkbox individually then the ng-model="payment.approved" in the repeating checkboxes is updated but this does not happen if they are checked with the checkAll function. Is it possible for angular to detect the boxes checked with checkAll()? I guess this is just putting off the same old inevitable slow-down to a slightly later point in the process.
Anyone have any ideas or work-arounds? Thanks!
I would use the ng-model to the best of its abilities. In your controller:
$onInit() {
// If you need this from a REST call to populate, you'll have to
// remember to do that here;
this.model = {
all: true,
items: {}
};
}
In your loop:
<tr>
<th>Table Header</th>
<th>
<input type="checkbox"
id="checkAllCheckBox"
ng-model="vm.model.all"
ng-change="vm.tickOrUntickAllCheckBoxes()" />
</tr>
<tr ng-repeat="payment in vm.payments track by $index">
<td ng-bind="payment.somePaymentValue"></td>
<td>
<input type="checkbox"
class="paymentsApprovalCheckbox"
ng-change="vm.approvedPayments($index)"
ng-model="vm.model.items[$index]" />
</td>
</tr>
Then in your controller:
tickOrUntickAllCheckBoxes() {
const boxes = this.model.items.length;
this.model.all = !this.model.all;
// Several ways to do this, forEach, map, etc.,
this.model.items.forEach((item) => { item.checked = !this.model.all });
}
And for setting it individually:
approvedPayments(idx) {
// Sets all the item's boxes checked, or unchecked;
this.model.items[idx].checked = !this.model.items[idx].checked;
// Possible call to extended model to get payment info;
handleCheckBoxClick(idx);
}
You should be able to put all the payment information into the one approvedPayments() method rather than have two separate methods (move logic out of template and into the controller or a service). I.e., your model could look like:
this.model.items = [
// One 'option' with id, payment etc;
{
id: 73,
paymentId: 73,
somePaymentValue: 210.73,
currencyType: 'GBP',
checked: false
},
{
// Another 'option' etc...
}
]
One issue to note is the incompatibility of ngChecked with ngModel, had to look it up (which is why I haven't used ng-checked in the above).
Thank to everyone for the suggestions. The solution I came up with was to push some of the work back to the server side. Instead of just loading the payments model (in which each payment record contains a lot of info) i am now loading two additional models when the page loads, one of which is a set of key/value pairs where the keys are payId and the values are all false and another one with the same keys and all values are true. Example:
{
"1": false,
"2": false
}
These are used for the checkAll/Uncheck all - just set the vm.approvedIDs variable to the true or false one. Then, the vm.approvedIDs variable is used as the model in the ng-repeat checkbox.
I have to do a bit of extra work on the server side when the user sends the approvedIDs back to the server to get only the key/id of the 'true' entries. Here are the relevant angular controller functions:
$onInit() {
// call http to get 'data' from server
vm.payments = data.payments;
vm.paymentIDsFalse = vm.approvedIDs = data.paymentIDsFalse;
vm.paymentIDsTrue = data.paymentIDsTrue;
};
// tick/untick all boxes
vm.tickOrUntickAllCheckBoxes = function(){
if (vm.allChecked == false) {
vm.approvedPayments = vm.paymentIDsFalse;
} else {
vm.approvedPayments = vm.paymentIDsTrue;
}
};
// tick/untick one box
vm.handleCheckBoxClick = function(payId, currentValue){
vm.approvedPayments[payId] = currentValue;
};
vm.submitApprovedIds = function(){
// post vm.approvedPayments to server
};
HTML:
<table>
<tbody>
<tr>
<th>Table Header</th>
<th><input type="checkbox" id="checkAllCheckBox" ng-model="vm.allChecked" ng-change="vm.tickOrUntickAllCheckBoxes()" />
</tr>
<tr ng-repeat="payment in vm.payments>
<td>{{ payment.somePaymentValue }}</td>
<td>
<input type="checkbox" class="paymentsApprovalCheckbox"
ng-value="payment.payId"
ng-model="vm.approvedPayments[payment.payId]"
ng-click="vm.handleCheckBoxClick(payment.payId, vm.approvedPayments[payment.payId])" />
</td>
</tr>
</tbody>
</table>
It looks to me as if there must be a better way than creating these additional models but it is working pretty smoothly for now and I can move on to the next thing!

MDL table retrieve data checked values

I'm using tables of MDL lib. https://getmdl.io/components/index.html#tables-section­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
But there are no docs how I can retrieve checked values about.
I found only this solution, but this not helping at all:
var checkboxes = document.getElementById('team-table-id')
.querySelector('tbody').querySelectorAll('.mdl-checkbox__input');
for (var i = 0; i < checkboxes.length; i++) {
checkboxes[i].addEventListener('change', function() {
console.log(this)
// returns <input type="checkbox" class="mdl-checkbox__input">
// how can I assign and retrieve value to/from this input?
});
}
How can I assign a value to checkbox/input of table rows at all?
How can I retrieve single checked values?
How can I handle "select all" event and get data of all rows?
Ok, I didn't find solution.
So I make my own for temporary:
1) Assign some class for tr's, so it can be found when check event happend
2) assign value for tr's. It can be serialized values or smth like that
3) listen check event and get data
Markup:
<table id="team-table-id" width="100%" class="mdl-data-table mdl-js-data-table mdl-data-table--selectable mdl-shadow--2dp">
<thead>
<tr class="row-info" data-value="all">
<th class="mdl-data-table__cell--non-numeric">Donation Invoice</th>
<th>Donation Name</th>
<th>Donation price</th>
</tr>
</thead>
<tbody>
<tr class="row-info" data-value="one more value">
<td class="mdl-data-table__cell--non-numeric">I-20170419120440</td>
<td>Some Donation Name</td>
<td>$2.90</td>
</tr>
<tr class="row-info" data-value="another value">
<td class="mdl-data-table__cell--non-numeric">C-20170419120454</td>
<td>Anothre</td>
<td>$1.25</td>
</tr>
<!--etc...-->
Javascript:
window.findAncestor = (el, cls) => {
while ((el = el.parentElement) && !el.classList.contains(cls));
return el;
}
let checkboxes = document.getElementById('team-table-id')
.querySelectorAll('.mdl-checkbox__input');
for (var i = 0; i < checkboxes.length; i++) {
checkboxes[i].addEventListener('change', function() {
console.log(findAncestor(this, 'row-info'))
});
// Returns parent table row, so you can get selected data.
// For example <tr data-value="some value" class="row-info">....
Please, feel free to suggest right one.
UPD:
This approach dnt have bugs and can hanlde all checked values, so I've marked this as "solved".
Have a look at https://github.com/google/material-design-lite/issues/1210 where several solutions (work-around) are presented depending on the version of MDL
I am following this (work-around)
On window.onload I am adding onclick attribute to all checkbox to call function getCheckValue(this), this function traverse through dom to get innerHTML of each td in tr
window.onload=function(){
var checkAll=document.getElementsByClassName('mdl-checkbox__input')
for(var i=0;i<checkAll.length;i++){
checkAll[i].setAttribute('onclick','getCheckValue(this)')
}
}
function getCheckValue(obj){
if(obj.checked){
/*th is checked in thead*/
if(obj.parentElement.parentElement.parentElement.parentElement.nodeName=='THEAD'){
var trs=obj.parentElement.parentElement.parentElement.parentElement.nextElementSibling.children
for(var i=0;i<trs.length;i++){
var tds=trs[i].getElementsByTagName('td')
for(var j=1;j<tds.length;j++){
console.log(tds[j].innerHTML)
}
}
}
else{
/*td inside tbody is checked*/
var tds=obj.parentElement.parentElement.parentElement.getElementsByTagName('td')
for(var i=1;i<tds.length;i++){
console.log(tds[i].innerHTML)
}
}
}else{
/* uncheck th checkbox of thead*/
if(obj.parentElement.parentElement.parentElement.parentElement.nodeName!='THEAD'){
obj.parentElement.parentElement.parentElement.parentElement.previousElementSibling.firstElementChild.firstElementChild.firstElementChild.classList.remove('is-checked')
obj.parentElement.parentElement.parentElement.parentElement.previousElementSibling.firstElementChild.firstElementChild.firstElementChild.firstElementChild.checked=false
}
}
}
Plunker link for demonstration

Check if values in checked row are equivalent

My application allows you to track orders in a store database. This database contains a weak entity used for notes which is attached to an orderID. I want to allow users to be able to apply to same 'note' to many orders at the same time, but there are some fields in the notes table that are dependent on the location of the sale. In other words, you should only be allowed to apply the same note if all the sale locations are the same.
Simplified View:
#using (Html.BeginForm("Create", "Note", FormMethod.Get, new { name = "editForm" }))
{
<table id="DataTable">
<tr>
<th>
<input type="button" value="Edit" onclick="checkboxValidation()"/>
</th>
<th>
#Html.DisplayNameFor(model => model.OrderID)
</th>
<th>
#Html.DisplayNameFor(model => model.location)
</th>
</tr>
#foreach (var item in Model)
{
<tr >
<td>
<input type="checkbox" name="ids" value="#item.orderID" />
</td>
<td>
#Html.ActionLink(item.OrderID.ToString(), "Details", "Search", new { orderID = item.orderID.ToString() }, null)
</td>
<td>
#Html.DisplayFor(modelItem => item.location)
</td>
</tr>
}
</table>
checkboxValidation() is a javascript function I wrote to check if at least 1 checkbox is checked. How would I add a check to make sure all of the locations on checked lines are the same? Is this even possible? Thanks
EDIT: I missed a detail. When clicking the edit button, if the check is successful, it submits the form, which brings up the notes editor.
Should be fairly straightforward using JQuery:
// find all the checked rows
var checkedItems = $("#DataTable").find("tr td input[type=checkbox]");
// construct a locations array for all checked items
var locations = [];
checkedItems.each(function(index, element) {
if ($(element).is(":checked")) {
locations.push($(this).closest("td").next("td").next("td").text().trim());
}
});
// confirm each location is the same
var valid = true;
locations.each(function(index, element) {
if (index > 0 && locations[index-1] != element) {
valid = false;
return;
}
});
One additional thing you might want to do, is add some data tags to your tr and td elements, so that you can write more robust selectors that won't break with a minor UI re-arrangement (like tr[data-role=check] and tr[data-role=location], etc).
(Using JQuery closest and and JQuery each.)

Categories