Reputation: 835
I am using Angular 1.4.8 and would like to put only the checked values of a list into an array. This array then needs to be the value of an object property, like this:
myObject = {
"myArray": [
"apple",
"orange",
"pear"
]
}
My HTML:
<div ng-app="myApp">
<div ng-controller="MainCtrl as vm">
<form name="myForm">
<ul>
<li ng-repeat="fruit in vm.fruits track by $index">
<label>
<input type="checkbox" ng-model="vm.myObject.myArray[$index]" ng-true-value="'{{fruit}}'" ng-false-value="undefined" />{{fruit}}
</label>
</li>
</ul>
</form>
<pre>myObject = {{vm.myObject | json}}</pre>
</div>
</div>
My JS:
angular.module('myApp', []);
angular.module('myApp').controller('MainCtrl', function() {
var vm = this;
vm.myObject = {
myArray: []
}
vm.fruits = ["apple", "orange", "pear", "naartjie"];
});
For easy reference, see this fiddle.
Note that when you check and then uncheck a list item, the array retains a value of null
. I do not want null
bound to the array because it adds to its length and this is causing issues with other code.
How can I ignore binding falsey values like null
, undefined
, etc...?
Upvotes: 1
Views: 139
Reputation: 835
The problem comes down to tracking by $index
. Removing $index
from this code:
<li ng-repeat="fruit in vm.fruits track by $index">
<label>
<input type="checkbox" ng-model="vm.myObject.myArray[$index]" ng-true-value="'{{fruit}}'" ng-false-value="undefined" />{{fruit}}
</label>
</li>
and replacing it with (key, value)
like this:
<li ng-repeat="(key, value) in vm.fruits track by value">
<label>
<input type="checkbox" ng-model="vm.myObject.myArray.value[key]" ng-change="vm.insertIntoArray(value)" ng-true-value="'{{value}}'" />{{value}}
</label>
</li>
solved my issue.
Although other answers to-date were helpful and contributed to the final solution, none included everything that I needed. See the updated fiddle for more details.
Upvotes: 0
Reputation: 21
You can create a function to add/remove the fruits from array.
Something like this:
vm.insertIntoArray = function(value){
var index = vm.fruitsArray.indexOf(value);
if(index === -1){
vm.fruitsArray.push(value);
}else{
vm.fruitsArray.splice(index,1);
}
}
Also, set ng-change attribute into your checkboxes.
<input type="checkbox" ng-model="vm.myObject.myArray[$index]" ng-change="vm.insertIntoArray(fruit)" ng-value="'{{fruit}}'"/>
Here's a working fiddle: https://jsfiddle.net/fwu045u0/
Upvotes: 1
Reputation: 8598
Based on your requirements I have implemented something along the lines of what you may want:
vm.boxChecked = function(item){
var index = vm.myObject.myArray.indexOf(item);
if(index !== -1)
vm.myObject.myArray.splice(index, 1);
else
vm.myObject.myArray.push(item);
};
The fiddle also will check any checkbox whose value appears in the myArray on load. You will see it auto checks 'apple' for you as I have put it in the array. IF you wish to remove this functionality, simply remove apple from the array and the ng-checked
portion of the directive and the behavior should be as you desire.
Upvotes: 1
Reputation: 6033
Look at this plunker for the same problem.
You can modify your model to track the selected items by adding some selected
property to the original objects, e.g.
<li ng-repeat="fruit in vm.fruits track by $index">
<label>
<input type="checkbox" ng-model="fruit.selected" ng-true-value="'{{fruit}}'" ng-false-value="undefined" />{{fruit}}
</label>
</li>
Then you have several solutions to build the array of selected elements:
with a function that filter the fruit
array on selected==true
property
with a watch on the fruits
collection that will update the selected array when an item is selected/unselected.
by adding `ng-change="toggleSelect(fruit)" in the input and managing a separate list of selected items
Upvotes: 0