AngularJS: uncheck checkboxes with no ng-model attribute - angularjs

I want to uncheck all checkboxes when press some button. I need to do this on AngularJS (no jQuery). My checkboxes don't have ng-model attribute. How I can uncheck them?
My HTML structure:
<li ng-repeat="channel in channelsList">
<div class="checkbox">
<label><input type="checkbox" value="" ng-click="isChecked(channel.id)">
<img src="images/checkbox-unchecked.png" alt="" class="unchecked">
<img src="images/checkbox.png" alt="" class="checked"><span>{{channel.name}}</span>
</label>
</div>
</li>
My channelsList is only an array of objects with 2 properties: id and name.
Thanks for helping!

Two ng-ifs
If you really want to avoid ng-model you could achieve the same effect with... notice the checked attribute
<li ng-repeat="channel in channelsList">
<div class="checkbox">
<label>
<input ng-if="isChecked(channel.id);" type="checkbox" checked ng-click="check(channel.id);">
<input ng-if="!isChecked(channel.id);" type="checkbox" ng-click="check(channel.id);">
<img src="images/checkbox-unchecked.png" alt="" class="unchecked">
<img src="images/checkbox.png" alt="" class="checked"><span>{{channel.name}}</span>
</label>
</div>
</li>

Bind checkbox ng-model to a _selected property.
Please note that I use _selected and not selected in case your API would in a near future return a selected property that would collide with this one.
index.html
<!doctype html>
<html lang="en" ng-app="app">
<head>
<meta charset="utf-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.min.js"></script>
<script src="script.js"></script>
</head>
<body ng-controller="SampleController">
<ul>
<li ng-repeat="channel in channelsList">
<input type="checkbox" ng-model="channel._selected" /> {{channel.name}} (id={{channel.id}})
</li>
</ul>
<button ng-click="uncheckAll()">Uncheck all</button>
</body>
</html>
script.js
angular.module('app', []);
angular.module('app').controller('SampleController', function ($scope) {
$scope.channelsList = [
{id: 'c1', name: 'CNN'},
{id: 'c2', name: 'BBC'},
{id: 'c3', name: 'Discovery Channel'}
];
$scope.uncheckAll = function() {
angular.forEach($scope.channelsList, function (channel) {
channel._selected = false;
});
};
});
Here is the plunker : http://plnkr.co/edit/VPOjKMUVyrMpPfT9jLz3

I don't know exactly what you need but supposing you have an array of ids telling the ids checked like this:
$scope.channelsList = [
{'id' : 1, 'name' : 'foo' },
{'id' : 2, 'name' : 'bar' },
{'id' : 3, 'name' : 'foo' }
];
var checked = [1, 3]
$scope.isChecked = function(id){
return checked.indexOf(id) >= 0;
};
You can put a button like:
<button ng-click="uncheckAll()">click</button>
And use it to clear your array:
$scope.uncheckAll = function(){
checked = [];
}

Related

ng-model saving with a recursive display

Setup
I have a frontend that displays a JSON. One can edit the values in the JSON via an ng-model textarea with a save button.
It does this by recursively calling an object like this:
In tree-object-edit.html:
...
<h4 class="capitalize">{{ item_key }}: </h4>
<textarea rows="2" cols="60" ng-model="item"></textarea>
<div ng-if="item.properties">
<ul>
<li ng-repeat="(item_key, item) in item.properties" ng-include="'html/tree-object.html'"></li>
</ul>
</div>
This is called by this my-definition.html
<form name="form"
role="form"
novalidate
class="ng-scope ng-invalid ng-invalid-required ng-dirty ng-valid-minlength"
ng-controller="MyDefinitionDetailController">
<h4>My Definition Edit: {{myDefinition.name}}</h4>
<ul ng-repeat="(item_key,item) in myDefinition" ng-include="'html/tree-object-edit.html'"></ul>
<button type="submit" ng-click="create()">
<span>Save</span>
</button>
</form>
My my-defintion-detail.controller.js contains
$scope.create = function () {
MyDefinition.save($scope.myDefinition,
function () {
});
};
Problem
Clicking save does not save the myDefintion because myDefiniton has not been changed. Only item has been changed.
Question
Is there a way to make the myDefiniton change when the item "within it" changes?
UPDATE 1
I have found that:
<textarea rows="2" cols="60" ng-model="myDefinition[item_key]"></textarea>
Does work for the first level of the recursion
You correctly noted, that ng-model="myDefinition[item_key]"(parent[key] at my example) works, - changes will reflect into desired model, if you will make them on property level not on direct value. So, besides passing value and key to nested template, you also should pass parent object, that way chain of references from actual value to "head" will be created:
angular.module('app', []).controller('ctrl', ['$scope', function($scope) {
$scope.value = {
identity: {
name: 'Max',
surName:'Smith',
},
birthDay: {
year: 1990,
month: 2,
day: {
weekDay: 'friday',
number: '13'
}
},
firstLevel: 'abc'
}
$scope.isObject = function(value){
return angular.isObject(value);
}
}])
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app='app' ng-controller="ctrl">
<script type="text/ng-template" id="template">
{{key}}
<ul ng-init='temp=value'>
<input ng-if='!isObject(value)' type='text' ng-model='parent[key]'/>
<li ng-if='isObject(temp)' ng-repeat='(key, value) in temp' ng-init='parent=temp' ng-include="'template'"></li>
</ul>
</script>
<ul ng-init='parent=value'>
<li ng-repeat='(key, value) in value' ng-include="'template'"></li>
</ul>
{{value | json}}
</div>
Just to add a perhaps more elegant solution: (Note if you update angular recursive directives also becomes a thing)
angular.module('app', ['dotjem.angular.tree']).controller('ctrl', ['$scope', function($scope) {
$scope.value = {
identity: {
name: 'Max',
surName:'Smith',
},
birthDay: {
year: 1990,
month: 2,
day: {
weekDay: 'friday',
number: '13'
}
},
firstLevel: 'abc'
}
$scope.isObject = function(value){
return angular.isObject(value);
}
}])
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://rawgithub.com/dotJEM/angular-tree-bower/master/dotjem-angular-tree.js"></script>
<div ng-app="app" ng-controller="ctrl">
<ul dx-start-with="value as parent">
<li ng-repeat="(key, value) in parent">
{{key}}
<input ng-if="!isObject(value)" type="text" ng-model="parent[key]"/>
<ul ng-if="isObject(value)" dx-connect="value"></ul>
</li>
</ul>
<pre>{{value | json}}
</pre>
</div>

angularjs- dropdown value should be number not object

I have an array of objects that looks like
$scope.pArray = [{id: 0, name: 'bob'}, {id: 1, name: 'jen'}];
In my select dropdown, Im using ng-options instead of ng-repeat like so:
<select id="province" name="item" ng-model="obj.name" required
ng-options="item.id as prov.name for item in pArray track by item.id"></select>
Now when I hit the submit button, the value of obj.name is an object instead of the integer (0 or 1). How can I change this so that instead of the object, I get the id?
You can try this,
<select ng-model="selected" ng-options="emp.name for emp in pArray ">
</select>
DEMO
var app = angular.module('todoApp', []);
app.controller("dobController", ["$scope",
function($scope) {
$scope.pArray = [{id: 0, name: 'bob'}, {id: 1, name: 'jen'}];
$scope.getselected = function(selected) {
alert(selected.id)
}
}
]);
<!DOCTYPE html>
<html ng-app="todoApp">
<head>
<title>To Do List</title>
<link href="skeleton.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.min.js"></script>
<script src="MainViewController.js"></script>
</head>
<body ng-controller="dobController">
<div class="col-md-20">
<div id="main">
<form class="form-horizontal" role="form">
<label class="control-label col-md-2">Filter List:</label>
<div class="col-md-5">
<select ng-model="selected" ng-options="emp.name for emp in pArray ">
</select>
</div>
<button type="button" class="btn btn-primary" ng-click="getselected(selected)">selected</button>
</form>
</div>
</div>
</body>
</html>
Referring to the the angular docs:
https://docs.angularjs.org/api/ng/directive/ngOptions
You should try:
ng-options="item as item.name for item in pArray track by item.id"
You should try changing the "item.id as" to "item as" since you are using track by item.id. Also, did you mean "item.name" and not "prov.name"
Anyway, that's just quick and hopefully helpful place to start.

angularjs get only selected checkbox

i want to get the selected checkboxes in my loop, for that check box i have to retrive the amount field onclick.
Here is my HTML script :
<div ng-repeat="$item in items">
Amount :<input ng-model="$item.daily_data.payment_amount">
Check : <input type=checkbox ng-model="checkAmount[$item.daily_data.id]" ng-value="$item.id" >
</div>
<input type="button" ng-click="checkNow()" />
The below script showing all check boxes . i want the only selected one.
JS Script :
$scope.checkAmount = {};
$scope.checkNow(){
console.log($scope.checkAmount);
}
First of all to use functions with $scope you should do something like this:
$scope.checkNow = function() {
...
}
or
$scope.checkNow = checkNow;
function checkNow() {
...
}
About your problem:
You could bind the checkboxes to a property (something like checked), so you can have the items that are checked easily in your controller.
Then, to calculate the total of all checked amount , I' suggest you to use Array.prototype.filter() + Array.prototype.reduce().
Here's a demo based on your original code:
(function() {
angular
.module("app", [])
.controller('MainCtrl', MainCtrl);
MainCtrl.$inject = ['$scope'];
function MainCtrl($scope) {
$scope.checkNow = checkNow;
$scope.checkAmount = {};
$scope.items = [
{
"id": 1
},
{
"id": 2
},
{
"id": 3
}
];
function checkNow() {
$scope.total = $scope.items.filter(function(value) {
return value.checked;
}).reduce(function(a, b) {
return a + b.amount;
}, 0);
}
}
})();
<!DOCTYPE html>
<html ng-app="app">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
</head>
<body ng-controller="MainCtrl">
<div ng-repeat="$item in items">
<label>
Amount: <input type="number" ng-model="$item.amount">
</label>
<label>
Check: <input type=checkbox ng-model="$item.checked">
</label>
</div>
<button type="button" ng-click="checkNow()">Check now</button>
<hr>
<label for="total">Total</label>
<input type="number" id="total" disabled ng-model="total">
</body>
</html>

angularjs checkbox ng-checked not working

I have the following code :-
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.min.js"></script>
</head>
<body ng-app="app" ng-controller="ctrl" ng-init="init()">
<div class="container" style="width:400px">
<div class="panel panel-default">
<div class="panel-body">
<form>
<div class="form-group">
<label for="selectedBasket">Select basket :</label>
<select id="selectedBasket" class="form-control" ng-model="selectedBasket" ng-options="b.name for b in baskets">
</select>
</div>
<div ng-repeat="f in fruits" class="checkbox">
<label>
<input type="checkbox" value="" ng-checked="selectedBasket !== null && selectedBasket.items.indexOf(f) !== -1">
{{ f }}
</label>
</div>
</form>
</div>
</div>
</div>
<script>
var app = angular.module('app', []);
app.controller('ctrl', function($scope) {
$scope.init = function() {
$scope.baskets = [{'name': 'mary', 'items': ['apple', 'orange']}, {'name': 'jane', 'items': ['banana']}];
$scope.fruits = ['apple', 'banana', 'cherry', 'orange', 'watermelon'];
$scope.selectedBasket = null;
};
});
</script>
</body>
</html>
if I select Mary or Jane, I can correctly see the correct items in their basket checked. However if I manually check all the fruits and then look at Mary or Jane, it doesn't exclude the items that are not in their baskets. Why is ng-checked failing?
Bonus question, is it best practise to set selectedBasket to null and checking for null in a directive assuming I want nothing as a default value, is there a better way?
You've got no ng-model in your checkbox so your manual action isn't registered anywhere.
ng-checked is only used to make a 'slave' checkbox it can take no manual action.
My guess is you should use a ng-model initialized to your ng-check value instead of using a ng-checked.
If you want to keep your ng-checked what you can do is :
<input type="checkbox" ng-click="selectedBasket.items.push(f)" ng-checked="selectedBasket !== null && selectedBasket.items.indexOf(f) !== -1">
in fact it's still wrong... must be tired, use a toogle function in your ng-click which add or remove the item should be better...
Had the same problem with ng-check, tried everything but nothing worked. I wanted to control the number of checked Items when clicked to 2, so I used the $Event sent with ng-click and disable it.
Here is a sample code:
<input type="checkbox" ng-click="toggleCheck($event, product._id);"
ng-checked="isChecked(product._id)">
$scope.toggleCheck($event, productId){
if ( $scope.featuredProducts.indexOf(productId) === -1) {
if ($scope.featuredProducts.length < 2) {
$scope.featuredProducts.push(productId);
}else {
$event.preventDefault();
$event.stopPropagation();
}
} else {
$scope.featuredProducts.splice( $scope.featuredProducts.indexOf(productId), 1);
}
}
$scope.isChecked(productId){
return ($scope.featuredProducts.indexOf(productId) !== -1);
}

Edit functionality in ng-controller

I am trying to display a list of objects from a controller and then trying to edit them.
I am binding data called editContact to value in input text box. I want to set a variable ii in scope and then when editing is done, then replace contacts[ii] with the temporary object editContact. But ii is not being recognized. Can I set a variable like ii?
<!doctype html>
<html ng-app>
<head>
<style>
</style>
<link rel="stylesheet" type="text/css" href="style.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js"></script>
</head>
<body>
<div ng-controller="contactsController">
<label>Name</label>
<input ng-model="name" type="text" placeholder="Name">
<label>email</label>
<input ng-model="email" type="text" placeholder="Email">
<button ng-click="addContact()">Add contact</button>
<div>{{contactsController.name}}</div>
<div>
<ul>
<li ng-repeat="contact in contacts">
<div>{{contact.name}}</div>
<div>{{contact.email}}</div>
<div><button ng-click="deleteContact($index)">delete</button></div>
<div><button ng-click="editContact($index)">Edit</button></div>
</li>
</ul>
<input type="text" value="{{editContact.name}}"/>
<input type="text" value="{{editContact.email}}"/>
<button ng-click="changeValue(ii)">Edit</button>
</div>
</div>
<script>
// Your code goes here.
// $( document ).ready(function() {
// alert('jQuery asdfas!');
// Your code here.
// });
function contactsController($scope){
$scope.contacts=[{name:'asdf',email:'asdf'},
{name:'yweuir',email:'xcvzx'}
];
contactsController.prototype.addContact =function(){
console.log(this.name);
console.log(this.email);
this.contacts.push({name:this.name,email:this.email});
}
$scope.changeValue=function(){
$scope.contacts[$scope.ii]=$scope.editContact;
}
$scope.editContact=function(i){
$scope.editContact=$scope.contacts[i]
$scope.ii=i;
}
}
</script>
</body>
</html>
First, in the DOM always bind attributes for input boxes with ngModel. Example:
<input type="text" ng-model="editContact.name"/>
Second, never use $index as a point of reference for finding things in your controller. You should use the object itself. Example:
<li ng-repeat="contact in contacts">
<button ng-click="editSomeContact(contact)"></button>
</li>
Then your JavaScript should look like this:
$scope.addContact = function() {
$scope.contacts.push({name: '', email: ''});
};
$scope.editSomeContact = function(contact) {
$scope.editContact = contact;
};
$scope.deleteContact = function(contact) {
var index = $scope.contacts.indexOf(contact);
if(index > -1) {
$scope.contacts.splice(index, 1);
}
if($scope.editContact === contact){
$scope.editContact = null;
}
};
At this point, you don't need a changeValue function because you'll see that the contacts in the list will update with the edited fields due to the fact that the values are dynamically bound in both places.

Resources