What I want to do with vue:
Count checked checkboxes
Set all checkboxes to checked (or uncheck all)
This is a very simplified model. The real website contains the following contraints:
The number of checkboxes changes.
The values are always different.
I do not want to put all the input-attribute into the data-section of
Vue
The following code allows to count the number of checked checkboxes.
<html>
<body>
<script src="https://unpkg.com/vue"></script>
<div id="app">
<input type="checkbox" name="abc" value=1 v-model="cch">
<input type="checkbox" name="abc" value=2 v-model="cch">
<br/>
Count: {{cch.length}}
</div>
<script>
new Vue({
el: '#app',
data: {
cch: [],
},
})
</script>
</body>
</html>
The following code checks all checkboxes (and, of course, unchecks the checkboxes if chk=false):
<html>
<body>
<script src="https://unpkg.com/vue"></script>
<div id="app">
<input type="checkbox" name="abc" value=1 :checked="chk">
<input type="checkbox" name="abc" value=2 :checked="chk">
<br/>
Checked: {{chk}}
</div>
<script>
new Vue({
el: '#app',
data: {
chk: true
},
})
</script>
</body>
</html>
It seems that it is not possible to use :checked and v-model in the same input-tag.
What can I do?
I have added a button to make all checkboxed checked and I have changed the names. The problems remain: the count works well, but the "all" button does not have any effect.
<html>
<body>
<script src="https://unpkg.com/vue"></script>
<div id="app">
<input type="checkbox" name="abc1" value=1 v-model="cch" :checked="chk">
<input type="checkbox" name="abc2" value=2 v-model="cch" :checked="chk">
<br/>
Count: {{cch.length}}
<br/>
<input type="button" #click="chk=!chk" value="all">
</div>
<script>
new Vue({
el: '#app',
data: {
cch: [],
chk: true
},
})
</script>
</body>
</html>
You'll need to set a unique name-attribute to each checkbox. That way they work correctly with v-model.
Related
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.
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);
}
Following app shows three todo items at first and
after adding an new data, it shows updated lists for a moment and go back to the original state.
Could you tell me why does it go back to the initial state automatically?
link for Pluker
http://plnkr.co/edit/h6THusBe7AWFle5ixXzX?p=preview
==================================
<!DOCTYPE html>
<html ng-app="initExample">
<head>
<link data-require="bootstrap-css#*" data-semver="3.3.1" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" />
<script src="https://code.angularjs.org/1.4.0-beta.5/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body class="well" ng-controller="ExampleController">
<h1> AngularJS Todo List</h1>
<p> Total <strong> {{todolist.length}} </strong> / Remain <strong> {{countRemain()}} </strong> </p>
<ul>
<li ng-repeat="todo in todolist" class="checkbox"> <input ng-model="todo.done" type="checkbox"> {{todo.title}}</li>
</ul>
<form name="newItemForm" class="form-inline" action="">
<div class="form-group">
<label class="sr-only" for="newItemText" placeholder="Type new ToDo"></label>
<input type="text" class="form-control" ng-model="newTodo" name="newItemText" placeholder="Type new Todo">
</div>
<button type="submit" ng-click="addNewTodo(newTodo)" class="btn btn-default"> Add </button>
</form>
</body>
</html>
============================
// Code goes here
var mymodule=angular.module('initExample', []);
mymodule.controller('ExampleController',
['$scope', function($scope) {
$scope.todolist = [
{done: true, title:'AngularJS study'},
{done: false, title:'music listening'},
{done: false, title:'run'}
];
$scope.countRemain = function() {
var count = 0;
var list = $scope.todolist;
angular.forEach(list, function(val, key) {
if(!list[key].done) count++;
});
return count;
};
$scope.addNewTodo = function(newTodo) {
todolist.push({done: false, title: newTodo});
};
}
]
);
Remove the action attribute from the form or add "preventDefault" from the button click.
Fixed the plunkr:
<form name="newItemForm" class="form-inline">
http://plnkr.co/edit/KFpbbdlDPbnIPAW43EaG?p=preview
P.S. also fixed the addNewTodo Function:
$scope.addNewTodo = function(newTodo) {
$scope.todolist.push({done: false, title: newTodo});
};
You need to remove action attribute from form definition, otherwise browser will try to submit it, reloading the page:
<form name="newItemForm" class="form-inline">
<!-- ... -->
</form>
Demo: http://plnkr.co/edit/MwTmGqzdELzUbrY82kKg?p=preview
I am trying to uncheck checkbox with submit button. The idea is when checkbox is checked button is shown, and when button is clicked checkbox is unchecked and button is hidden.
HTML page:
<html ng-app="myApp" ng-controller="myCtrl">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js"></script>
<script src="script.js"></script>
<meta charset=utf-8 />
</head>
<body>
<div ng-repeat="foo in boxes">
<div>
<input type="checkbox" name="cb" id="cb" ng-model="show" />{{foo}}
</div>
<div ng-show="show">
<form ng-submit="submit()">
<input type="submit" name="sumbit" id="sumbit" value="Hide" />
</form>
</div>
</div>
</body>
</html>
JS:
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.boxes = ['a','b','c'];
$scope.submit = function(){
$scope.show = false;
}
});
On Plukner: http://plnkr.co/edit/z9W0w18dkgYJ3D5Q3aR2?p=preview
Thanks for any help!
The problem is that you're using a single variable to store states of 3 items yet Angular creates a scope for each context in the ng-repeat iteration. By changing show to an array and using $index to reference each of them, the show array from the main scope is passed to all three child scopes and there are no conflicts, so it works:
app.controller('myCtrl', function($scope) {
$scope.boxes = ['a','b','c'];
$scope.show = [];
$scope.submit = function(){
$scope.show = [];
}
});
HTML
<div ng-repeat="foo in boxes">
<div>
<input type="checkbox" name="cb" id="cb" ng-model="show[$index]" />{{foo}}
</div>
<div ng-show="show[$index]">
<form ng-submit="submit()">
<input type="submit" name="sumbit" id="sumbit" value="Hide" />
</form>
</div>
</div>
See it here: http://plnkr.co/edit/kfTMaLTXWtpt7N9JVHAQ?p=preview
(note sure if this is exactly what you wanted because there's no question, but it's enough to get you started)
UPDATE
And here is the version where Hide unchecks only "its own" checkbox ($scope.submit now accepts the index parameter): http://plnkr.co/edit/YVICOmQrPeCCUKP2tBBl?p=preview
You need to change the html code and simplify it as
Instead of form use simple ng-click
<div ng-show="show">
<input type="submit" value="Hide" ng-click="show = !show" />
</div>
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.