Angular to disable ng-repeat checkbox based on value - javascript

I have a list of checkbox displayed using ng-repeat, now i need to disable some checkbox based on specific value checkbox is checked.
checkbox display code
<div class="checkbox">
<label ng-repeat="specific in specifications">
<input ng-click="onClick(specific, newObject[specific])" id="specifications_chk" value="{{specific}}" ng-model="newObject[specific]" type="checkbox">
{{specific}}
</label>
</div>
Here am using ng-click function to disable checkbox.
This is my controller code:
$scope.onClick = function(sp, checked){
if(sp == 'Sofa_Cleaning' && checked === true){
angular.element(document.getElementById('specifications_chk'))[0].disabled = true;
}
if(sp == 'Sofa_Cleaning' && checked === false){
angular.element(document.getElementById('specifications_chk'))[0].disabled = false;
}
};
html view:
in controller code am able disable only first value (IndepthHomeCleaning), so how can i disable Room_Cleaning, Kitchen_Cleaning, and Carpet_cleaning when Sofa_Cleaning is checked
Am i stuck with this, Help will be really appreciated

I don't know why you are still stick with the jquery. You are getting
by id when you are trying to disable the checkbox.
.
In html, id should be unique for the current html page. y ou are
having duplicated ids and you are getting the first value from the
array using [o] when you are trying to disable.
.
If you strictly want solution from the same method then use the
following methodology Use class name instead of id for the check boxes and use
angular element and disable.
The following code should be used where you need to disable. Use appropriate code based on your need.
angular.forEach(document.getElementsByClassName('checkbox1'), function(value, key) {
angular.element(value)[0].disabled = true;
debugger
});

If you want to change specifications array you need a new array and mapping.
Define new row object for each specification.
Access specification row and its prop (is active or is disable) from your specification.
http://jsfiddle.net/ms403Ly8/87/
function testCtrl($scope, $filter) {
$scope.specifications = ["IndepthHomeCleaning", "Room_Cleaning", "Kitchen_Cleaning", "Carpet_cleaning", "Sofa_Cleaning"];
$scope.specificationRows = [];
$scope.newRow = function(spec) {
var newSpec = {
SpecName: spec,
IsDisabled: false,
IsClicked: false
};
$scope.specificationRows.push(newSpec);
};
$scope.getRowObject = function(sp) {
return $filter('filter')($scope.specificationRows, {
SpecName: sp
})[0];
};
$scope.getRowStatus = function(spec) {
console.log($filter('filter')($scope.specificationRows, {
SpecName: spec
})[0].IsDisabled);
return $scope.getRowObject(spec).IsDisabled;
};
$scope.onClick = function(sp) {
$scope.getRowObject(sp).IsClicked = !$scope.getRowObject(sp).IsClicked;
if (sp == 'Sofa_Cleaning') {
$scope.getRowObject("Carpet_cleaning").IsDisabled = $scope.getRowObject(sp).IsClicked;
$scope.getRowObject("Kitchen_Cleaning").IsDisabled = $scope.getRowObject(sp).IsClicked;
$scope.getRowObject("Room_Cleaning").IsDisabled = $scope.getRowObject(sp).IsClicked;
}
};
}
getRowObject is example. Maybe it's not best practice. You can change this function.

You should not have same id for multiple elements in your code. You need to make you elements ids unique.
HTML :
<div ng-app ng-controller="LoginController">
<div class="checkbox">
<label ng-repeat="specific in specifications">
<input id="specifications_chk{{$index}}" ng-click="onClick(specific, newObject[specific])" value="{{specific}}" ng-model="newObject[specific]" type="checkbox" /> {{specific}}
<br>
</label>
</div>
</div>
JavaScript :
function LoginController($scope) {
$scope.specifications = ['IndepthHomeCleaning',
'Room_Cleaning',
'Kitchen_Cleaning',
'BathroomCleaning',
'Carpet_cleaning',
'Sofa_Cleaning'
];
$scope.newObject = {
'IndepthHomeCleaning': 1,
'Room_Cleaning': 2,
'Kitchen_Cleaning': 3,
'BathroomCleaning': 4,
'Carpet_cleaning': 5,
'Sofa_Cleaning': 6
};
$scope.onClick = function(sp, checked) {
if (sp == 'Sofa_Cleaning' && checked === true) {
angular.element(document.getElementById('specifications_chk1'))[0].disabled = true;
angular.element(document.getElementById('specifications_chk2'))[0].disabled = true;
angular.element(document.getElementById('specifications_chk4'))[0].disabled = true;
}
if (sp == 'Sofa_Cleaning' && checked === false) {
angular.element(document.getElementById('specifications_chk1'))[0].disabled = false;
angular.element(document.getElementById('specifications_chk2'))[0].disabled = false;
angular.element(document.getElementById('specifications_chk3'))[0].disabled = false;
}
};
}
JsFiddle : https://jsfiddle.net/nikdtu/f7k3kcwn/

use ng-disabled
var angApp = angular.module('myApp', []);
angApp.controller('MyController', function MyController($scope) {
$scope.specifications = [{"text":"IndepthHomeCleaning ", "disabled":false, "checked":false},
{"text":"Room_Cleaning", "disabled":false, "checked":false},
{"text":"Kitchen_Cleaning", "disabled":false, "checked":false},
{"text":"BathroomCleaning", "disabled":false, "checked":false},
{"text":"Carpet_cleaning", "disabled":false, "checked":false},
{"text":"Sofa_Cleaning", "disabled":false, "checked":false}];
$scope.onClick = function(sp, checked){
console.log(sp, checked);
if(sp.text == 'Sofa_Cleaning' && checked){
$scope.specifications[1].disabled = true;
$scope.specifications[2].disabled = true;
$scope.specifications[4].disabled = true;
}
if(sp.text == 'Sofa_Cleaning' && !checked){
$scope.specifications[1].disabled = false;
$scope.specifications[2].disabled = false;
$scope.specifications[4].disabled = false;
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyController">
<div class="checkbox">
<label ng-repeat="specific in specifications" style="display:block">
<input ng-disabled="specific.disabled" ng-change="onClick(specific, specific.checked)" id="specifications_chk" value="specific.checked}" ng-model="specific.checked" type="checkbox">
{{specific.text}}
</label>
</div>
</div>

I think you're over complicating this. Your data object should be simplified to look like this
$scope.specifications = [
{name: 'Sofa_Cleaning', active: false},
{name: 'Carpet_Cleaning', active: false},
{name: 'Room_Cleaning', active: false},
{name: 'Kitchen_Cleaning', active: false},
{name: 'BathroomCleaning', active: false}
];
Template:
<input type="checkbox"
ng-bind="specific.name"
ng-model="specific.active"
ng-disabled="shouldDisable(specific)">
in your controller
$scope.disableWhenSofaIsChecked = ['Room_Cleaning','Kitchen_Cleaning','Carpet_Cleaning'];
$scope.shouldDisable = function(specific) {
var disable = $scope.disableWhenSofaIsChecked;
if(disable.indexOf(specific.name) > -1) {
for(var obj in $scope.specifications) {
if(obj.name === 'Sofa_Cleaning') {
return obj.active;
}
}
}
return false;
}
EDIT
So if you're getting specifications data from API, you can just do this:
SomeApi
.get()
.then(function(results){
// Assuming it's a promise. End result is the same for a passed-in callback
// Assuming results is an array of names
$scope.specifications = results.map(function(item){
return {
name: item,
active: false
};
});
});

You are using 'id' attribute which should be unique for each DOM element. So definitely your solution will take single element. So you should try using class attribute and document.getElementbyClass function.

Don't use jquery to for dom manipulation.
Use ng-change instead of ng-click. This will be the appropriate one.
Here I've update a plunkr.
Here for the simple example, I've done like
if the value is check5 then disable all the checkboxes. Otherwise enable the checkboxes.
https://jsfiddle.net/AvGKj/517/
Note: I've used little bit old plugin. Please take the logics alone
<div ng-controller="MyCtrl">
<table>
<tr ng-repeat="appObj in myAppObjects">
<td>
<input type="checkbox" ng-model="appObj.cb1"
ng-disabled="appObj.disable"
ng-change="Disable(appObj,myAppObjects)">
{{appObj.value}}
</td>
</tr>
</table>
{{myAppObjects}}
<br>list of checked items: {{checkedItems()}}
</div>
function MyCtrl($scope) {
$scope.myAppObjects = [
{id:1,value:'check1'},
{id:2,value:'check2'},
{id:3,value:'check3'},
{id:4,value:'check4'},
{id:5,value:'check5'}
];
$scope.Disable=function(appObj,list)
{
if(appObj.value=="check5")
{
for(var i=0; i<list.length;i++)
{
if(list[i].value!="check5")
{
if(appObj.cb1==true)
{
list[i].disable=true;
}
else{
list[i].disable=false;
}
}
}
}
}
}

Related

Validating different types of form inputs with criterias

I want to get the answers to a form upon submission and parse them to JSON.
This works quite good but I want some validation before sending the data.
I tried a lot of variations of the snippet down below but am still stuck.
Steps:
Prevent default event on "send"
Get Form
Iterate through the elements of the form
Eliminate empty items and their value
If checkbox is checked: value = true
Store correct items in data
Return data
Somehow I can't get to work steps 4 and 5 work at the same time, every time I get one of them to work I screw over the other one.
In this snippet, the checkbox works as intented but the textfield doesn't:
If anybody can point me in the right direction with the if/else statements or something like that it would be greatly appreciated.
document.addEventListener('DOMContentLoaded', function(){
var data = {};
var formToJSON = function formToJSON(form) {
var data = {};
for (var i = 0; i < form.length; i++) {
var item = form[i];
//looking for checkbox
if (item.value =="") {
continue;
}
else {
if (item.checked == false) {
data[item.name] = false;
}
else {
data[item.name] = item.value;
}
}
}
return data; };
var dataContainer = document.getElementsByClassName('results__display')[0];
form = document.getElementById('formular').querySelectorAll('input,select,textarea');
butt = document.getElementById('knopfabsenden');
butt.addEventListener('click', function (event) {
event.preventDefault();
handleFormSubmit(form = form);
});
var handleFormSubmit = function handleFormSubmit(event) {
var data = formToJSON(form);
dataContainer.textContent = JSON.stringify(data, null, " ");
}
}, false);
<div id="formular">
<label class="formular__label" for="machineName">Textfield Test</label>
<input class="formular__input formular__input--text" id="machineNumber" name="machineNumber" type="text"/>
<br>
<input class="formular__input formular__input--checkbox" id="checkTest" name="checkTest" type="checkbox" value="true"/>
<label class="formular__label formular__label--checkbox" for="checkTest">Checkbox Test</label>
<br>
<button class="formular__button" id="knopfabsenden" type="submit">Submit</button>
</div>
<div class="results">
<h2 class="results__heading">Form Data</h2>
<pre class="results__display-wrapper"><code class="results__display"></code></pre>
</div>
The problem is .checked will always be false if it doesn't exist. So the text field gets the value false.
for (var i = 0; i < form.length; i++) {
var item = form[i];
//looking for checkbox
if (item.value ==="") {
continue;
}
else {
if (item.type === "text") {
data[item.name] = item.value;
}
else if (item.type === "checkbox"){
data[item.name] = item.checked;
}
}
}
In this code snippet I check the type of the input and handle it accordingly. also notice I use the === operator and not the == operator as a best practice (Difference between == and === in JavaScript)

Validate checkbox with AngularJs

Again i'm having trouble with checkboxes. I'm getting info from an API and showing like checkbox. The problem comes when i'm triying to add a validation. This is a part of my code:
(function() {
'use strict';
var fact = {
templateUrl: './app/components/fact.components.html',
controller: factCtrl
};
angular.module('fApp').component('odcFacturas', fact);
factCtrl.$inject = ["$scope", "couponApi"];
function factCtrl($scope, couponApi) {
var vm = this;
vm.clientOrder = null;
vm.all = false;
vm.sendData = function() {
vm.apiData = couponApi.get({
idOrder: vm.idOrder
}).$promise.then(function(data) {
for (var i = 0; i < data.Response.length; i++) {
data.Response[i].Select = vm.all;
}
vm.coupons = data.Response;
vm.combo = data.Response.length > 0;
});
}
Here i call the info, and the next part of my code check all the checkboxes:
vm.selectAll = function() {
for (var i = 0; i < vm.coupons.length; i++) {
vm.coupons[i].Select = vm.all;
}
if (vm.all == 0) {
alert("Select at least one coupon");
}
}
How can I trigger three validations with a submit button? I mean: what I want to do is validate three cases:
if the checkbox "select all checkboxes" is checked, submit
if there's no selected checkboxes, show the alert message
if there's at least one checkbox (or 'n' checkboxes) selected,
submit
On the HTML view i have this:
<div class ="container-fluid">
<div class="row">
<div class="col-md-6">
<div class="cbx input-group">
<div class="checkbox" name="imtesting" ng-show="$ctrl.coupons.length > 0">
<label><input type="checkbox"
ng-show="$ctrl.coupons.length > 0"
name="allCoupons"
ng-model="$ctrl.all"
ng-click="$ctrl.selectAll()"/>Select all coupons</label>
<ul>
<li ng-repeat="c in $ctrl.coupons">
<input type="checkbox"
name="couponBox"
ng-model="c.Select"
ng-click="$ctrl.result()"
required/>{{c.CodeCoupon}}
<br>
</li>
</ul>
<label class="label label-danger" ng-show="submitted == true && !ctrl.newTest()">Select at least one coupon</label>
</div>
</div>
</div>
</div>
Hope you can help me.
Thanx in advance.
You can use the Select property from each coupon object like
vm.canSubmit = function() {
for(var i = 0; i< vm.coupons.length; i++)
{
if (vm.coupons[i].Select) {
return true;
}
}
return false;
}
Redo the way you are handling your selectsAll function. When you are using angular there is a thing called scope.$apply that is actually running which tells the dom to update if the object or properties have changed. Sometimes if you use for loops the way you are using them it wont register a change.
Try this and it should work:
vm.selectAll = function()
{
vm.all = !vm.all;
vm.coupons.forEach(function(o){
o.Select = vm.all;
})
}
vm.submit = function(){
var checked = 0;
vm.coupons.forEach(function(o){
if(o.Select === true)
checked +=1;
})
if(vm.all || checked > 0){
//submit here
}
else if(checked === 0){
//error
}
}
This will work both ways. If checked it will check all and if unchecked it will uncheck all. That validation will work for all three scenarios.

List.js filter by radio button

I'm trying to filter by radio button using List.js
The List.js is working fine, but I cannot figure out how to make it work by using radio buttons. Please assist.
Here is the fiddle:
Jfiddle
Here is the javascript part:
var dap_list = new List('dap_list', {
valueNames: ['waste_name', 'client_name', 'created_by', 'timestamp', 'dap_status'],
page: 8,
plugins: [
ListPagination({})
]
});
$('#search_radio').change(function() {
var selection = this.value;
// filter items in the list
dap_list.filter(function(item) {
if (item.values().search_radio == selection) {
return true;
} else {
return false;
}
});
});
You have made three small mistakes in your fiddle.
You forgot to include jQuery itself (click the "Javascript" button with the little gear on it)
Your radio buttons have he same ID. That's illegal in HTML. Remove the IDs, you don't need them.
You want to filter your items on dap_status, not on search_radio.
So, with this knowledge, we get:
$(':radio[name=search_radio]').change(function () {
var selection = this.value;
dap_list.filter(function (item) {
return item.values().dap_status == selection;
});
});
Note that
if (booleanCondition) {
return true;
} else {
return false;
}
is an anti-pattern. Don't do that, simply return booleanCondition; like I did above.
You have to change the duplicate IDs in your HTML.
<label class="radio-inline">
<input type="radio" class="search" name="search_radio" id="search_radio1" value="Awaiting Approval">Awaiting Approval
</label>
<label class="radio-inline">
<input type="radio" class="search" name="search_radio" id="search_radio2" value="Needs Further Review">Needs Further Review
</label>
<label class="radio-inline">
<input type="radio" class="search" name="search_radio" id="search_radio3" value="Approved">Approved
</label>
For the JS you can use:
var dap_list = new List('dap_list', {
valueNames: ['waste_name', 'client_name', 'created_by', 'timestamp', 'dap_status'],
page: 8,
plugins: [
ListPagination({})
]
});
$('.search').change(function() {
var selection = this.value;
dap_list.filter(function(item) {
var status = item.values().dap_status;
return status == selection;
});
});

Javascript validation - group validation - if one entered, then all required

Using just jQuery (not validation plugin) I have devised a way to do a "if one, then all" requirement, but it's not at all elegant.
I'm wondering if someone can come up with a more elegant solution? This one uses some loop nesting and I'm really not pleased with it.
if ($("[data-group]")) {
//Store a simple array of objects, each representing one group.
var groups = [];
$("[data-group]").each(function () {
//This function removes an '*' that is placed before the field to validate
removeCurError($(this));
var groupName = $(this).attr('data-group');
//If this group is already in the array, don't add it again
var exists = false;
groups.forEach(function (group) {
if (group.name === groupName)
exists = true;
});
if (!exists) {
var groupElements = $("[data-group='" + groupName + "']");
var group = {
name: groupName,
elements: groupElements,
trigger: false
}
group.elements.each(function () {
if (!group.trigger) {
group.trigger = $(this).val().length !== 0;
}
});
groups.push(group);
}
});
//Now apply the validation and alert the user
groups.forEach(function (group) {
if (group.trigger) {
group.elements.each(function () {
//Make sure it's not the one that's already been filled out
if ($(this).val().length === 0)
// This function adds an '*' to field and puts it into a
// a sting that can be alerted
appendError($(this));
});
}
});
You don't have to store the groups in an array, just call the validateGroups function whenever you want to validate the $elements. Here is a working example http://jsfiddle.net/BBcvk/2/.
HTML
<h2>Group 1</h2>
<div>
<input data-group="group-1" />
</div>
<div>
<input data-group="group-1" />
</div>
<h2>Group 2</h2>
<div>
<input data-group="group-2" value="not empty" />
</div>
<div>
<input data-group="group-2" />
</div>
<div>
<input data-group="group-2" />
</div>
<button>Validate</button>
Javascript
function validateGroups($elements) {
$elements.removeClass('validated');
$elements.each(function() {
// Return if the current element has already been validated.
var $element = $(this);
if ($element.hasClass('validated')) {
return;
}
// Get all elements in the same group.
var groupName = $element.attr('data-group');
var $groupElements = $('[data-group=' + groupName + ']');
var hasOne = false;
// Check to see if any of the elements in the group is not empty.
$groupElements.each(function() {
if ($(this).val().length > 0) {
hasOne = true;
return false;
}
});
// Add an error to each empty element if the group
// has a non-empty element, otherwise remove the error.
$groupElements.each(function() {
var $groupElement = $(this);
if (hasOne && $groupElement.val().length < 1) {
appendError($groupElement);
} else {
removeCurError($groupElement);
}
$groupElement.addClass('validated');
});
});
}
function appendError($element) {
if ($element.next('span.error').length > 0) {
return;
}
$element.after('<span class="error">*</span>');
}
function removeCurError($element) {
$element.next().remove();
}
$(document).ready(function() {
$('button').on('click', function() {
validateGroups($("[data-group]"));
});
});
You might get some milage out of this solution. Basically, simplify and test your solution on submit click before sending the form (which this doesn't do). In this case, I simply test value of the first checkbox for truth, and then alert or check the required boxes. These can be anything you like. Good luck.
http://jsfiddle.net/YD6nW/1/
<form>
<input type="button" onclick="return checkTest()" value="test"/>
</form>
and with jquery:
checkTest = function(){
var isChecked = $('input')[0].checked;
if(isChecked){
alert('form is ready: input 0 is: '+isChecked);
}else{
$('input')[1].checked = true;
$('input')[2].checked = true;
}
};
//create a bunch of checkboxes
$('<input/>', {
type: 'checkbox',
html: 'tick'
}).prependTo('form');
$('<input/>', {
type: 'checkbox',
html: 'tick'
}).prependTo('form');
$('<input/>', {
type: 'checkbox',
html: 'tick'
}).prependTo('form');

Select all radio buttons which are checked with prototype

I have several input elements which look like this:
<input type="radio" checked="checked" value="1" name="handle[123]" />
<input type="radio" checked="checked" value="2" name="handle[456]" />
The number inside the name attribute is an object id i need. Now what I want to do is:
Fetch all input which are of type="radio" and are checked with prototype
Put all ids and values in an associative array
...so the resulting array looks something like this:
array{ 1 => 123, 2 => 456 }
Any ideas?
Here's what I came up with:
var results = [];
document.body.select('input[type=radio]:checked').each(function (element) {
var object = {};
object[element.value] = element.name.match(/\d+/)[0];
results.push(object);
});
new Ajax.Request('/some_url', {
method: 'post',
parameters: results
});
Demo
To get the checked radio button given a form id, and the name of the radio group:
function RF(el, radioGroup) {
if($(el).type && $(el).type.toLowerCase() == 'radio') {
var radioGroup = $(el).name;
var el = $(el).form;
} else if ($(el).tagName.toLowerCase() != 'form') {
return false;
}
var checked = $(el).getInputs('radio', radioGroup).find(
function(re) {return re.checked;}
);
return (checked) ? $F(checked) : null;
}
var value = RF('form_id', 'radio_grp_name');
Hope it helps
$$('input:checked[type=radio]').each(function (ele) {
output[ele.name.match(/\d+/)[0]] = ele.value;
});
This would give the desired output using prototype

Categories

Resources