I fill the table with a ADODB.Recordset. I have 25 rows. But it can change. And last column is checkboxes.
Only one checkbox can select. Check one and uncheck others automatic.
<input class="cb" id="txtdurum_<%=counter%>" name="txtdurum" type="checkbox" />
Help please :)
Try this code. Add an onchange event to each input checkbox.
<input class="cb" id="txtdurum_<%=counter%>" name="txtdurum" type="checkbox" onchange="check(this)"/>
JS:
function check(element){
if(element.checked){
var checkboxes = document.getElementsByClassName('cb');
for(var i=0;i<checkboxes.length;i++){
if(checkboxes[i]!=element)
checkboxes[i].checked = false;
}
}
}
Example Fiddle.
You can use jQuery:
$('.cb').change(function(){
$('.cb').prop('checked',false);
$(this).prop('checked',true);
});
This adds a change-listener to all checkboxes with the "cb" class-Attribute.
Place that code-fragment into the jquery-ready-function.
Example: JSFiddle
UPDATE1:
If you also want to enable, that the user can uncheck all:
$('.cb').change(function(){
var checkState = $(this).prop('checked');
$('.cb').prop('checked',false);
$(this).prop('checked', checkState);
});
Example: JSFiddle2
But:
better use radiobuttons
While I would – strongly – recommend that you use <input> elements of type="radio" (with a 'choose nothing' option, if that's required), I was intrigued enough to spend the last few hours putting together this approach.
This is one way of doing it, it feels little over-the-top and it's not quite as streamlined as I'd like, but it does suffice to meet your requirements. I've provided a simple demo for the introduction, and the JavaScript is commented throughout:
var Limit = (function () {
// private to this function, but shared by all instances:
// simple 'closest' function;
// start: DOM Node,
// needle: String, the tagName of the ancestor to find.
// if no ancestor exists (we stop at the <body> element)
// function returns null:
var closest = function (start, needle) {
// we begin at the 'start' node, but use
// the 'current' variable as a pointer as
// we move through the ancestors:
var current = start,
// converting the tagName to lower-case,
// for predictable comparisons:
find = needle.toLowerCase();
// while the tagName of the current element-node is not
// what we're looking for AND the current element-node is
// not the <body> element:
while (current.tagName.toLowerCase() !== find && current.tagName.toLowerCase() !== 'body') {
// we set the current node to its parentNode,
// thereby ascending through the DOM:
current = current.parentNode;
}
// if the tagName of the current element-node is 'body'
// we return null, otherwise we return that current node:
return current.tagName.toLowerCase() === 'body' ? null : current;
};
return function (groupSelector) {
// protected variables, available on a
// per-instance basis:
// the array in which we'll hold the selected
// <input> elements as they're checked:
var checked = [],
// the group of elements to which this instance
// will apply:
group = document.querySelectorAll(groupSelector),
// the defaults:
// allowInvalidity, Boolean:
// true: allows the user to select more than
// the maximum number of choices.
// false: prevents the selection of options
// beyond the maxumum number.
// fifo, Boolean:
// true: should the user try to select more
// than the maximum number of choices
// the first element in the array is
// removed.
// false: should the user try to select more
// than the maximum number of choices
// subsequent choices are prevented.
// maxChoices, Number:
// defines the maximum number of choices
// that can be made.
// parentErrorClass, String:
// the class-name to be applied to the
// parent of the <input> elements when
// the user chooses more than the maximum
// number of options (requires
// settings.invalidity to be true).
defaults = {
'allowInvalidity': false,
'fifo': true,
'maxChoices': 1,
'parentErrorClass': 'error'
};
// the object containing the function(s) we
// make available:
return {
// opts is the user-defined settings
// passed in:
'nOnly': function (opts) {
// a simple, though potentially costly,
// means of avoiding JavaScript's
// pass-by-reference (which prevents
// settings = dafaults from working),
// here creating a copy via the JSON functions:
var settings = JSON.parse(JSON.stringify(defaults));
// iterating over the user-defined settings in the
// supplied opts object:
for (var setting in opts) {
// avoiding iterating over inherited properties
// from the Object.prototype:
if (opts.hasOwnProperty(setting)) {
// setting the settings options to
// those supplied in the opts object:
settings[setting] = opts[setting];
}
}
// iterating over the Array-like NodeList returned by
// document.querySelectorAll() (when we retrieved the
// nodes for this 'group'), using Function.prototype.call()
// to apply Array.prototype.forEach():
Array.prototype.forEach.call(group, function (input) {
// there are three arguments available to
// Array.prototype.forEach(), the names are
// user-defined (within variable-naming constraints);
// the first (here: 'input') the current array-element
// from the array over which we're iterating,
// the second (not used) is the index of that array-element,
// the third (not used) is the full array over which
// we iterate.
// here we bind the anonymous function as the 'change'
// event-handler on each of the <input> elements in
// the parent group:
input.addEventListener('change', function (event) {
if (input.checked && settings.allowInvalidity === false) {
// add the <input> to the checked array:
checked.push(input);
// if too many choices have been made:
if (checked.length > settings.maxChoices) {
// we call Array.prototype.pop() (if
// settings.fifo is true) or
// Array.prototype.shift() (if
// settings.fifo is not exactly-true)
// to select the first element of the
// checked Array (shift()) or the last
// element (pop()) and set that element's
// checked property to false. Using shift()
// or pop() also removes it from the array:
checked[settings.fifo === true ? 'shift' : 'pop']().checked = false;
}
} else if (input.checked && settings.allowInvalidity === true) {
// we simply add the <input> to the array:
checked.push(input)
} else {
// we test that the <input> element is in
// the checked Array:
if (checked.indexOf(input) > -1) {
// using Array.prototype.splice() to
// remove it from the Array; using
// Array.prototype.indexOf() (again)
// to retrieve its index in the Array:
checked.splice(checked.indexOf(input), 1);
}
}
// iterating over the group, with Array.prototype.forEach():
Array.prototype.forEach.call(group, function (input) {
// if the <input> is not checked, or the number of choices
// is less than the permitted maximum:
if (!input.checked || checked.length <= settings.maxChoices) {
// we remove the parentErrorClass from the parentNode:
input.parentNode.classList.remove(settings.parentErrorClass);
// otherwise if the <input> is checked, AND
// there are too many choices:
} else if (input.checked && checked.length > settings.maxChoices) {
// we add the parentErrorClass to the parentNode:
input.parentNode.classList.add(settings.parentErrorClass);
}
});
});
});
}
};
};
})();
new Limit('.group1 input').nOnly({
'allowInvalidity': true,
'maxChoices': 3
});
new Limit('.group2 input').nOnly({
'maxChoices': 1,
'fifo': false
});
new Limit('.group3 input').nOnly({
'allowInvalidity': true,
'maxChoices' : 2,
'parentErrorClass' : 'oops'
});
var Limit = (function() {
var closest = function(start, needle) {
var current = start,
find = needle.toLowerCase();
while (current.tagName.toLowerCase() !== find && current.tagName.toLowerCase() !== 'body') {
current = current.parentNode;
}
return current.tagName.toLowerCase() === 'body' ? null : current;
};
return function(groupSelector) {
var checked = [],
group = document.querySelectorAll(groupSelector),
defaults = {
'allowInvalidity': false,
'fifo': true,
'maxChoices': 1,
'parentErrorClass': 'error'
};
return {
'nOnly': function(opts) {
var settings = JSON.parse(JSON.stringify(defaults));
for (var setting in opts) {
if (opts.hasOwnProperty(setting)) {
settings[setting] = opts[setting];
}
}
Array.prototype.forEach.call(group, function(input) {
input.addEventListener('change', function(event) {
if (input.checked && settings.allowInvalidity === false) {
checked.push(input);
if (checked.length > settings.maxChoices) {
checked[settings.fifo === true ? 'shift' : 'pop']().checked = false;
}
} else if (input.checked && settings.allowInvalidity === true) {
checked.push(input)
} else {
if (checked.indexOf(input) > -1) {
checked.splice(checked.indexOf(input), 1);
}
}
Array.prototype.forEach.call(group, function(input) {
if (!input.checked || checked.length <= settings.maxChoices) {
input.parentNode.classList.remove(settings.parentErrorClass);
} else if (input.checked && checked.length > settings.maxChoices) {
input.parentNode.classList.add(settings.parentErrorClass);
}
});
});
});
}
};
};
})();
new Limit('.group1 input').nOnly({
'allowInvalidity': true,
'maxChoices': 3
});
new Limit('.group2 input').nOnly({
'maxChoices': 1,
'fifo': false
});
new Limit('.group3 input').nOnly({
'allowInvalidity': true,
'maxChoices': 2,
'parentErrorClass': 'oops'
});
form {
-moz-column-count: 3;
-webkit-column-count: 3;
column-count: 3;
-moz-break-inside: avoid-column;
-webkit-break-inside: avoid-column;
break-inside: avoid-column;
}
label {
display: block;
border: 2px solid transparent;
transition: all 0.5s linear;
}
.error {
border: 2px solid #f00;
}
.oops {
background-color: #f90;
}
<form action="#" method="post">
<fieldset>
<legend>Group 1</legend>
<label class="group1">input 1
<input type="checkbox" />
</label>
<label class="group1">input 2
<input type="checkbox" />
</label>
<label class="group1">input 3
<input type="checkbox" />
</label>
<label class="group1">input 4
<input type="checkbox" />
</label>
<label class="group1">input 5
<input type="checkbox" />
</label>
</fieldset>
<fieldset>
<legend>Group 2</legend>
<label class="group2">input 1
<input type="checkbox" />
</label>
<label class="group2">input 2
<input type="checkbox" />
</label>
<label class="group2">input 3
<input type="checkbox" />
</label>
<label class="group2">input 4
<input type="checkbox" />
</label>
<label class="group2">input 5
<input type="checkbox" />
</label>
</fieldset>
<fieldset>
<legend>Group 3</legend>
<label class="group3">input 1
<input type="checkbox" />
</label>
<label class="group3">input 2
<input type="checkbox" />
</label>
<label class="group3">input 3
<input type="checkbox" />
</label>
<label class="group3">input 4
<input type="checkbox" />
</label>
<label class="group3">input 5
<input type="checkbox" />
</label>
</fieldset>
</form>
External JS Fiddle demo, for experimentation.
To apply this to your own situation, the function can be called like so:
// here, the only difference is the CSS selector
// passed to the Constructor:
new Limit('table input[type=checkbox]').nOnly({
'maxChoices': 1
});
var Limit = (function() {
var closest = function(start, needle) {
var current = start,
find = needle.toLowerCase();
while (current.tagName.toLowerCase() !== find && current.tagName.toLowerCase() !== 'body') {
current = current.parentNode;
}
return current.tagName.toLowerCase() === 'body' ? null : current;
};
return function(groupSelector) {
var checked = [],
group = document.querySelectorAll(groupSelector),
defaults = {
'allowInvalidity': false,
'fifo': true,
'maxChoices': 1,
'parentErrorClass': 'error'
};
return {
'nOnly': function(opts) {
var settings = JSON.parse(JSON.stringify(defaults));
for (var setting in opts) {
if (opts.hasOwnProperty(setting)) {
settings[setting] = opts[setting];
}
}
Array.prototype.forEach.call(group, function(input) {
input.addEventListener('change', function(event) {
if (input.checked && settings.allowInvalidity === false) {
checked.push(input);
if (checked.length > settings.maxChoices) {
checked[settings.fifo === true ? 'shift' : 'pop']().checked = false;
}
} else if (input.checked && settings.allowInvalidity === true) {
checked.push(input)
} else {
if (checked.indexOf(input) > -1) {
checked.splice(checked.indexOf(input), 1);
}
}
Array.prototype.forEach.call(group, function(input) {
if (!input.checked || checked.length <= settings.maxChoices) {
input.parentNode.classList.remove(settings.parentErrorClass);
} else if (input.checked && checked.length > settings.maxChoices) {
input.parentNode.classList.add(settings.parentErrorClass);
}
});
});
});
}
};
};
})();
new Limit('table input[type=checkbox]').nOnly({
'maxChoices': 1
});
<table>
<tr>
<td>row 1</td>
<td>
<input type="checkbox" />
</td>
</tr>
<tr>
<td>row 2</td>
<td>
<input type="checkbox" />
</td>
</tr>
<tr>
<td>row 3</td>
<td>
<input type="checkbox" />
</td>
</tr>
<tr>
<td>row 4</td>
<td>
<input type="checkbox" />
</td>
</tr>
<tr>
<td>row 5</td>
<td>
<input type="checkbox" />
</td>
</tr>
<tr>
<td>row 6</td>
<td>
<input type="checkbox" />
</td>
</tr>
<tr>
<td>row 7</td>
<td>
<input type="checkbox" />
</td>
</tr>
<tr>
<td>row 8</td>
<td>
<input type="checkbox" />
</td>
</tr>
<tr>
<td>row 9</td>
<td>
<input type="checkbox" />
</td>
</tr>
<tr>
<td>row 10</td>
<td>
<input type="checkbox" />
</td>
</tr>
</table>
External JS Fiddle demo, for experimentation.
This is, obviously, a representative demonstration since you neglected to provide the relevant (mcve) HTML, however since it relies only on an appropriate selector it should be easily applicable to your situation.
References:
CSS:
Attribute-selectors ([attribute=value]).
column-count.
CSS transitions.
JavaScript:
Array.prototype.forEach().
Array.prototype.indexOf().
Array.prototype.push().
Array.prototype.shift().
Array.prototype.splice().
Conditional/ternary Operator (assesment ? ifTrue : ifFalse).
document.querySelector().
document.querySelectorAll().
Element.classList API.
EventTarget.addEventListener().
for...in loop.
Function.prototype.call().
JSON.parse().
JSON.stringify().
Node.parentNode.
Node.tagName.
Object.prototype.hasOwnProperty().
String.prototype.toLowerCase().
Related
here you can see what I want to implement
Hey I'm stuck at this: I want that the launch button gets enabled after all checkboxes are checked and all ranges are set to max.
But something like this won't work:
while(checkboxes.unchecked && ranges.value !== '100') {
if (checkboxes.checked && ranges.value == '100')
document.getElementById('launch').disabled = false;
}
Any tipps for implementation?
The example below uses the HTMLFormElement interface to reference <form>, <input>, and <button> (<fieldset> and <legend> as well if it was needed), you should notice it's terse syntax compared to the standard HTMLElement interfaces.
Solution
Wrap everthing in a <form> tag if you haven't already. Also assign a [name] shared between all ranges and a different [name] shared between all checkboxes. Reference it, then bind the event handler (ie allFields(e)) to the <form> and listen for the "change" event.
const form = document.forms[0];
form.onchange = allFields;
By default all event handlers pass the Event Object (e, event, evt, etc). Reference the <form> with this keyword coupled with the .elements property. That will result in a HTMLCollection of all <input>, <button>, <fieldset>, and <legend> within <form>.
function allFields(e) {
const io = this.elements;
...
Next, reference all form controls assigned [name="chx"] (all checkboxes) and collect them into a HTMLCollection then convert it into a real array. Do so for all [name="rang"] (all ranges) as well.
const chx = [...io.chx];
const rng = [...io.rng];
Then run each array through the Array method .every() which will return true if all elements in the array are true for a given conditional. The condition for the ranges is .value === '100' and for the checkboxes is .checked === true.
let allChecked = chx.every(c => c.checked === true);
let allMaxRange = rng.every(r => r.value === '100');
Finally compare allChecked and allMaxRange.
if (allChecked === true && allMaxRange === true) {
io.launch.disabled = false;
} else {
io.launch.disabled = true;
}
const form = document.forms[0];
form.onchange = allFields;
function allFields(e) {
const io = this.elements;
const chx = [...io.chx];
const rng = [...io.rng];
let allChecked = chx.every(c => c.checked === true);
let allMaxRange = rng.every(r => r.value === '100');
if (allChecked === true && allMaxRange === true) {
io.launch.disabled = false;
} else {
io.launch.disabled = true;
}
};
input,
button {
display: inline-block;
font-size: 100%;
line-height: 1.15;
}
button {
cursor: pointer;
}
fieldset {
height: max-content;
}
[type="range"] {
width: 80%;
}
[type="checkbox"] {
margin-top: -20px;
}
<form>
<fieldset>
<legend>
<button id='launch' type='button' disabled>Launch</button>
</legend>
<input name='chx' type='checkbox'>
<input name='rng' type='range' value='100'><br>
<input name='chx' type='checkbox' checked>
<input name='rng' type='range' value='100'><br>
<input name='chx' type='checkbox' checked>
<input name='rng' type='range' value='100'><br>
<input name='chx' type='checkbox' checked>
<input name='rng' type='range' value='100'><br>
<input name='chx' type='checkbox' checked>
<input name='rng' type='range' value='100'><br>
<input name='chx' type='checkbox' checked>
<input name='rng' type='range' value='100'><br>
</fieldset>
</form>
Try this approach :
You need to iterate over all checkbox elements as well as range elements.
Then use a flag variable to verify if all checkboxes/ranges are checked/max.
Use onchange/oninput event handlers. -> while loop is not necessary
I'm fairly new to angular and have a select all checkbox that checks all the boxes through ng-model/ng-checked.
<th>
<input type="checkbox" id="selectAll" ng-model="selectAll"/>
</th>
<th>
${Case Number}
</th>
<tr ng-repeat="item in c.onbCase>
<td><input type="checkbox" name="checkbox" ng-click="checkboxFunc(item)"
ng-model="item.checked"
ng-checked="selectAll || item.checked"/>
</td>
<td>{{item.number}}</td>
</tr>
I also have a function called checkboxFunc that sets item.selected to true if checked and throws the case number into an array:
$scope.onbNum = [];
$scope.checkboxFunc = function(item){
if(item.selected == false) {
if($scope.onbNum.indexOf(item.number)==-1){
$scope.onbNum.push(
item.number
)
}
item.selected = true;
} else {
if($scope.onbNum.indexOf(item.number)!==-1){
var pos = $scope.onbNum.indexOf(item.number);
$scope.onbNum.splice(pos,1)
}
item.selected = false;
}
}
While the Select All checkbox checks all the boxes when clicked upon, how do I fix my function so that all the case numbers get thrown into the array?
Don't use ng-checked and ng-model together on the same element.
From the Docs:
Note that [the ng-checked] directive should not be used together with ngModel, as this can lead to unexpected behavior.
— AngularJS ng-checked Directive API Reference
If you are using item.checked just to ensure which check box is checked then you can do something like this :
$scope.onbCase = [
{ number:1, selected:false },
{ number:2, selected:false },
{ number:3, selected:false }
];
Here is your functions :
$scope.onbNum = [];
$scope.checkAll = function(){
$scope.onbNum = [];
for(var i=0; i<$scope.onbCase.length;i++){
$scope.onbCase[i].selected = $scope.selectAll;
}
if($scope.selectAll === true){
for(var i=0; i<$scope.onbCase.length;i++){
$scope.onbNum.push($scope.onbCase[i].number);
}
}
}
$scope.checkboxFunc = function(item){
if(item.selected) {
if($scope.onbNum.indexOf(item.number)===-1){
$scope.onbNum.push(
item.number
)
}
}
else {
var pos = $scope.onbNum.indexOf(item.number);
if(pos>-1){
$scope.onbNum.splice(pos,1);
}
$scope.selectAll = false;
}
}
Here is your HTML Page :
<th>
<input type="checkbox" id="selectAll" ng-model="selectAll"
ng-click="checkAll()"/>
</th>
<th> ${Case Number}
</th>
<tr ng-repeat="item in onbCase">
<td><input type="checkbox" name="checkbox"
ng-click="checkboxFunc(item)" ng-model="item.selected"
ng-checked="selectAll || item.selected"/>
</td>
<td>{{item.number}}</td>
</tr>
Hope this will work or give you a idea for what you want.
I'm not sure to exactly know your question , but I hope my answer help you:
add ng-click to your selectAll input like below:
<input type="checkbox" id="selectAll" ng-model="selectAll" ng-change="checkAll()" />
and also add below function to you controller:
$scope.checkAll = function () {
if ($scope.selectAll == true) {
angular.forEach($scope.c.onbCase, function(item) {
if ($scope.onbNum.indexOf(item.number) == -1) {
$scope.onbNum.push(
item.number
);
}
});
} else {
angular.forEach($scope.c.onbCase, function (item) {
if ($scope.onbNum.indexOf(item.number) !== -1) {
var pos = $scope.onbNum.indexOf(item.number);
$scope.onbNum.splice(pos, 1);
}
});
}
}
I have a table that has a checkbox. It has a select ALL javascript function and a select one by one function. My html file looks like this for the delete button:
<button data-toggle="modal" data-target="#rejectModal" contenteditable="false" id="delbutton" ng-model="delbutton" ng-disabled="countChecked() == 0">Delete</span></button>
Select All Checkbox:
<th class="">
<input type="checkbox" name="select" id="checkAll" ng-model="selectAllRawSCP"/>
</th>
table details:
<tr ng-repeat=" item in rawSCAP | orderBy:sort">
<td>
<input type="checkbox" name="select" value="checked" ng-model="item.checked"/>
</td>
I used the code I saw in one of the answers here in stack overflow to disable the delete button if there is no checkbox checked. It looks like this:
$scope.countChecked = function(){
var count = 0;
angular.forEach($scope.rawSCAP, function(value){
if (value.checked) count++;
});
return count;
}
But using this, my page returns an error which isTypeError: Cannot read property 'checked' of null
And also I need to enable delete button even if I used select all
The error is pretty clear, it cannot access the property checked of the rawSCAP itens. You have to guarantee rawSCAP itens checked property is not null before you try to use it in ng-model.
You could try to initialize it before with some value you want. Check this on how to do it.
There are some conditions you need to follow to use the <<ng-model>>.checked, which is a plain array can't be used for checkbox, it must be an array of objects. Also please change your function to below.
$scope.countChecked = function() {
var count = 0;
angular.forEach($scope.rawSCAP, function(value) {
value.checked = value.checked || 0;
if (value.checked) count++;
});
return count;
}
The main line which does the work is value.checked = value.checked || 0; Here if the value.checked is undefined, then the 0 will get assigned to value.checked, hence you won't get the error!
var app = angular.module('myApp', []);
app.controller('MyController', function MyController($scope) {
$scope.rawSCAP = [{
item: 1
}, {
item: 2
}, {
item: 3
}, {
item: 4
}, {
item: 5
}, {
item: 6
}, {
item: 7
}];
$scope.countChecked = function() {
var count = 0;
angular.forEach($scope.rawSCAP, function(value) {
value.checked = value.checked || 0;
if (value.checked) count++;
});
return count;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-controller='MyController' ng-app="myApp">
<button data-toggle="modal" data-target="#rejectModal" contenteditable="false" id="delbutton" ng-model="delbutton" ng-disabled="countChecked() == 0">Delete</button>
<table>
<th class="">
<input type="checkbox" name="select" id="checkAll" ng-model="selectAllRawSCP" />
</th>
<tr ng-repeat=" item in rawSCAP | orderBy:sort">
<td>
<input type="checkbox" name="select" value="checked" ng-model="item.checked" />{{item.item}}
</td>
</tr>
</table>
</div>
I want to check all the checkboxes upon checking the "Selectall" checkbox and vice versa if I select all the checkboxes one by one then the "Selectall" checkbox should be automatically get checked. If I uncheck any of it's child checkboxes then the "Select all" checkbox should also be unchecked.
In my code, all the things are working except one thing that
if I select all the checkboxes one by one then the "Selectall" checkbox should be automatically get checked. Can anyone help me in making this thing workable for me. For your reference I'm giving my file code (HTML and Javascript code) here, so that you could test on your local machine.:
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js">
</script>
<script>
$(document).ready(function () {
$("#ckbCheckAll").click(function () {
$(".checkBoxClass").prop('checked', $(this).prop('checked'));
});
$(".checkBoxClass").change(function(){
if (!$(this).prop("checked")){
$("#ckbCheckAll").prop("checked",false);
}
});
});
</script>
</head>
<body>
<input type="checkbox" id="ckbCheckAll" /> Check All
<p id="checkBoxes">
<input type="checkbox" class="checkBoxClass" id="Checkbox1" />
<br />
<input type="checkbox" class="checkBoxClass" id="Checkbox2" />
<br />
<input type="checkbox" class="checkBoxClass" id="Checkbox3" />
<br />
<input type="checkbox" class="checkBoxClass" id="Checkbox4" />
<br />
<input type="checkbox" class="checkBoxClass" id="Checkbox5" />
<br />
</p>
</body>
</html>
You can check how many checkboxes are there and how many are checked:
$(".checkBoxClass").change(function(){
var all = $('.checkBoxClass');
if (all.length === all.filter(':checked').length) {
$("#ckbCheckAll").prop("checked", true);
} else {
$("#ckbCheckAll").prop("checked", false);
}
});
Not sure if all can be just $(this);
In addition to the selectAll checkbox I have experimented with adding selectRow and selectCol checkboxes to get the same effect for each row and column of the grid of checkboxes.
see http://jsfiddle.net/wf_bitplan_com/snpc2L34/29/
/**
* http://stackoverflow.com/questions/432493/how-do-you-access-the-matched-groups-in-a-javascript-regular-
* expression
* examples:
*
* var matches = getRegexMatches(/(dog)/, "dog boat, cat car dog");
* console.log(matches);
*
* var matches = getRegexMatches(/(dog|cat) (boat|car)/, "dog boat, cat car");
* console.log(matches);
*/
function getRegexMatches(regex, string) {
if(!(regex instanceof RegExp)) {
return "ERROR";
}
else {
if (!regex.global) {
// If global flag not set, create new one.
var flags = "g";
if (regex.ignoreCase) flags += "i";
if (regex.multiline) flags += "m";
if (regex.sticky) flags += "y";
regex = RegExp(regex.source, flags);
}
}
var matches = [];
var match = regex.exec(string);
while (match) {
if (match.length > 2) {
var group_matches = [];
for (var i = 1; i < match.length; i++) {
group_matches.push(match[i]);
}
matches.push(group_matches);
}
else {
matches.push(match[1]);
}
match = regex.exec(string);
}
return matches;
}
/**
* get the select_row or select_col checkboxes dependening on the selectType row/col
*/
function getSelectCheckboxes(selectType) {
var regex=new RegExp("select_"+selectType+"_");
var result= $('input').filter(function() {return this.id.match(regex);});
return result;
}
/**
* matrix selection logic
* the goal is to provide select all / select row x / select col x
* checkboxes that will allow to
* select all: select all grid elements
* select row: select the grid elements in the given row
* select col: select the grid elements in the given col
*
* There is a naming convention for the ids and css style classes of the the selectors and elements:
* select all -> id: selectall
* select row -> id: select_row_row e.g. select_row_2
* select col -> id: select_col_col e.g. select_col_3
* grid element -> class checkBoxClass col_col row_row e.g. checkBoxClass row_2 col_3
*/
$(document).ready(function () {
// handle click event for Select all check box
$("#selectall").click(function () {
// set the checked property of all grid elements to be the same as
// the state of the SelectAll check box
var state=$("#selectall").prop('checked');
$(".checkBoxClass").prop('checked', state);
getSelectCheckboxes('row').prop('checked', state);
getSelectCheckboxes('col').prop('checked', state);
});
// handle clicks within the grid
$(".checkBoxClass").on( "click", function() {
// get the list of grid checkbox elements
// all checkboxes
var all = $('.checkBoxClass');
// all select row check boxes
var rows = getSelectCheckboxes('row');
// all select columnn check boxes
var cols = getSelectCheckboxes('col');
// console.log("rows: "+rows.length+", cols:"+cols.length+" total: "+all.length);
// get the total number of checkboxes in the grid
var allLen=all.length;
// get the number of checkboxes in the checked state
var filterLen=all.filter(':checked').length;
// console.log(allLen+"-"+filterLen);
// if all checkboxes are in the checked state
// set the state of the selectAll checkbox to checked to be able
// to deselect all at once, otherwise set it to unchecked to be able to select all at once
if (allLen == filterLen) {
$("#selectall").prop("checked", true);
} else {
$("#selectall").prop("checked", false);
}
// now check the completeness of the rows
for (row = 0; row < rows.length; row++) {
var rowall=$('.row_'+row);
var rowchecked=rowall.filter(':checked');
if (rowall.length == rowchecked.length) {
$("#select_row_"+row).prop("checked", true);
} else {
$("#select_row_"+row).prop("checked", false);
}
}
});
$('input')
.filter(function() {
return this.id.match(/select_row_|select_col_/);
}).on( "click", function() {
var matchRowColArr=getRegexMatches(/select_(row|col)_([0-9]+)/,this.id);
var matchRowCol=matchRowColArr[0];
// console.log(matchRowCol);
if (matchRowCol.length==2) {
var selectType=matchRowCol[0]; // e.g. row
var selectIndex=matchRowCol[1]; // e.g. 2
// console.log(this.id+" clicked to select "+selectType+" "+selectIndex);
// e.g. .row_2
$("."+selectType+"_"+selectIndex)
.prop('checked', $("#select_"+selectType+"_"+selectIndex).prop('checked'));
}
});
});
Use jQuery( ":checkbox" )
Maybe you can look # selectors of jquery http://api.jquery.com/category/selectors/
//----------Select AllCheckBoxes Begin ------------------------
function toggleChkBox() {
$('#tblPermissionDetails td input:checkbox').prop('checked', $('#chkSelectAll')[0].checked);
}
//----------Select AllCheckBoxes End --------------------------
//----------Check/Uncheck SelectAll checkbox based on other checkboxes Begin----------------
$('#tblPermissionDetails td input:checkbox').change(function() {
if (!$(this).prop("checked")) {
$("#chkSelectAll").prop("checked", false);
} else {
var PermissionList = [];
var PermissionListChecked = [];
$('#tblPermissionDetails td input:checkbox').each(function() {
PermissionList.push(this.name);
})
$('#tblPermissionDetails td input:checkbox:checked').each(function() {
PermissionListChecked.push(this.name);
})
if (PermissionList.length == PermissionListChecked.length) {
$("#chkSelectAll").prop("checked", true);
}
}
});
//----------Check/Uncheck SelectAll checkbox based on other checkboxes End------------------
<table class="table table-striped" id="tblPermissionDetails">
<thead>
<tr>
<th>Sl.No</th>
<th>Permission</th>
<th>Description</th>
<th><input type="checkbox" id="chkSelectAll" onclick="toggleChkBox();" />(Select All)</th>
</tr>
</thead>
<tbody>
#{ int i = 1; List
<FDSApp.Models.RolePermissionDetailsModel> permissionModel = Model; foreach (var item in permissionModel) {
<tr>
<td>#i</td>
<td>#item.PermissionName</td>
<td>#item.Description</td>
<td>#Html.CheckBox(#item.PermissionId.ToString(), #item.IsEnabled == 0 ? false : true)</td>
</tr>
i = i + 1; } }
</tbody>
</table>
In my view model I have a IsMale value that has the value true or false.
In my UI I wish to bind it to the following radio buttons:
<label>Male
<input type="radio" name="IsMale" value="true" data-bind="checked:IsMale"/>
</label>
<label>Female
<input type="radio" name="IsMale" value="false" data-bind="checked:IsMale"/>
</label>
The problem I think is checked expects a string "true" / "false". So my question is, how can I get this 2-way binding w/ this UI and model?
I know this is an old thread, but I was having the same problem and found out a much better solution that was probably added to knockout after this question was officially answered, so I'll just leave it for people with the same problem.
Currently there is no need for extenders, custom binding handlers or computeds.
Just provide a "checkedValue" option, it will use that instead of the html 'value' attribute, and with that you can pass any javascript value.
<input type="radio" name="a" data-bind="checked:IsChecked, checkedValue: true"/>
<input type="radio" name="a" data-bind="checked:IsChecked, checkedValue: false"/>
Or:
<input type="radio" name="b" data-bind="checked:Quantity, checkedValue: 1"/>
<input type="radio" name="b" data-bind="checked:Quantity, checkedValue: 2"/>
<input type="radio" name="b" data-bind="checked:Quantity, checkedValue: 3"/>
One option is to use a writeable computed observable.
In this case, I think that a nice option is to make the writeable computed observable a "sub-observable" of your IsMale observable. Your view model would look like:
var ViewModel = function() {
this.IsMale = ko.observable(true);
this.IsMale.ForEditing = ko.computed({
read: function() {
return this.IsMale().toString();
},
write: function(newValue) {
this.IsMale(newValue === "true");
},
owner: this
});
};
You would bind it in your UI like:
<label>Male
<input type="radio" name="IsMale" value="true" data-bind="checked:IsMale.ForEditing"/>
</label>
<label>Female
<input type="radio" name="IsMale" value="false" data-bind="checked:IsMale.ForEditing"/>
</label>
Sample: http://jsfiddle.net/rniemeyer/Pjdse/
This works for me:
http://jsfiddle.net/zrBuL/291/
<label>Male
<input type="radio" name="IsMale" value="1" data-bind="checked:IsMale"/>
</label>
<label>Female
<input type="radio" name="IsMale" value="0" data-bind="checked:IsMale"/>
</label>
ko.bindingHandlers['radiobuttonyesno'] = {
'init': function (element, valueAccessor, allBindingsAccessor) {
var stateHandler = function (property, allBindingsAccessor, key, value, checkIfDifferent) {
if (!property || !ko.isObservable(property)) {
var propWriters = allBindingsAccessor()['_ko_property_writers'];
if (propWriters && propWriters[key])
propWriters[key](value);
} else if (ko.isWriteableObservable(property) && (!checkIfDifferent || property.peek() !== value)) {
property(value);
}
};
var updateHandler = function () {
var valueToWrite;
if ((element.type == "radio") && (element.checked)) {
valueToWrite = element.value;
} else {
return; // "radiobuttonyesno" binding only responds to selected radio buttons
}
valueToWrite = (valueToWrite === "True") ? true : false;
var modelValue = valueAccessor(), unwrappedValue = ko.utils.unwrapObservable(modelValue); //can be true of false
stateHandler(modelValue, allBindingsAccessor, 'checked', valueToWrite, true);
};
ko.utils.registerEventHandler(element, "click", updateHandler);
// IE 6 won't allow radio buttons to be selected unless they have a name
if ((element.type == "radio") && !element.name)
ko.bindingHandlers['uniqueName']['init'](element, function () { return true });
},
'update': function (element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
value = value ? "True" : "False";
if (element.type == "radio") {
element.checked = (element.value == value);
}
}
};
Use this binder instead of creating stupid ko computed observables.
Example:
<label>Male
<input type="radio" name="IsMale" value="True" data-bind="radiobuttonyesno:IsMale"/>
</label>
<label>Female
<input type="radio" name="IsMale" value="False" data-bind="radiobuttonyesno:IsMale"/>
</label>
Once you figure out that the initial match for the radio button wants to match only a string and wants to set the value to a string, it is simply a matter of converting your initial value to string. I had to fight this with Int values.
After you have setup your observables, convert the value to string and KO will do its magic from there. If you are mapping with individual lines, do the conversion in those lines.
In the example code, I'm using Json to map the whole Model in a single command.
Then letting Razor insert the value between the quotes for the conversion.
script type="text/javascript">
KoSetup.ViewModel = ko.mapping.fromJS(#Html.Raw(Json.Encode(Model)));
KoSetup.ViewModel.ManifestEntered("#Model.ManifestEntered"); //Bool
KoSetup.ViewModel.OrderStatusID("#Model.OrderStatusID"); //Int
</script>
I use a "Dump it all to the screen" at the bottom of my web page during development.
<h4>Debug</h4>
<pre data-bind="text: ko.toJSON($data, null, 2)"></pre>
Here are the data values, Before
"OrderStatusID": 6,
"ManifestEntered": true,
and, After
"OrderStatusID": "6",
"ManifestEntered": "True",
In my project, I didn't need to convert Bools, because I'm able to use a checkbox that doesn't have the same frustration.
Why not simply true and false instead of 1 and 0?
<label>Male
<input type="radio" name="IsMale" value="true" data-bind="checked:IsMale"/>
</label>
<label>Female
<input type="radio" name="IsMale" value="false" data-bind="checked:IsMale"/>
</label>
You can also use an extender so it's easy to reuse them for more observables:
ko.extenders.boolForEditing = function (target, allowNull) {
var result = ko.computed({
read: function () {
var current = target();
var newValue = null;
if (current === undefined || current === null || current === '') {
if (!allowNull) {
newValue = 'false';
}
} else {
newValue = current ? 'true' : 'false';
}
return newValue;
},
write: function (newValue) {
var current = target();
var valueToWrite = null;
if (newValue === undefined || newValue === null || newValue === '') {
if (!allowNull) {
valueToWrite = false;
}
} else {
valueToWrite = newValue === 'true';
}
// only write if it changed
if (valueToWrite !== current) {
target(valueToWrite);
} else {
if (newValue !== current) {
target.notifySubscribers(valueToWrite);
}
}
}
}).extend({
notify: 'always'
});
result(target());
return result;
};
Then use it like this:
this.IsMale.forEditing = this.IsMale.extend({boolForEditing: true});
The parameter provided to boolForEditing indicates whether the value may be null.
See http://jsfiddle.net/G8qs9/1/
After doing lot of research for older version of knockout prior to 3.0 there are possibly two best options
Create a knockout extender like
ko.extenders["booleanValue"] = function (target) {
target.formattedValue = ko.computed({
read: function () {
if (target() === true) return "True";
else if (target() === false) return "False";
},
write: function (newValue) {
if (newValue) {
if (newValue === "False") target(false);
else if (newValue === "True") target(true);
}
}
});
target.formattedValue(target());
return target;
};
To use the extender on your model, you’d do something like the following:
function Order() {
this.wantsFries= ko.observable(false).extend({ booleanValue: null });
}
<span>Do you want fries with that?</span>
<label>
<input type="radio" name="question" value="True"
data-bind="value: wantsFries.formattedValue" /> Yes
</label>
<label>
<input type="radio" name="question" value="False"
data-bind="value: wantsFries.formattedValue" /> No
</label>
source:http://www.timlabonne.com/2013/02/building-a-knockout-js-extender-for-boolean-values/