I am using a number of checkboxes to push their values to an array to be used as arguments for the filtering of a dataset.
The requirement is to:
Show child filters on selection of the parent category.
If parent is unchecked all its children should be unchecked (false) automatically (otherwise they will be hidden and still true)
Display active filters
remove active filter on click (also uncheck their corresponding checkbox programatically).
Clear all filters and uncheck all checkboxes.
My current code is below, however see attached fiddle.
$scope.IsChecked = false;
$scope.ActiveFilters = [];
$scope.clearFilters = function() {
$scope.ActiveFilters = [];
};
$scope.ModifyFilter = function (IsChecked, Filter) {
console.log(IsChecked);
if (IsChecked) {
$scope.ActiveFilters.push(Filter);
}
else {
var indexz = $scope.ActiveFilters.indexOf(Filter);
$scope.ActiveFilters.splice(indexz, 1);
}
};
A fiddle with a semi-working demonstration is here
-- EDIT --
Further explanation: When a checkbox is checked it pushed its value to the array. if I remove this from the array by clicking on its name in the 'Active Filters' section at the bottom of the fiddle then it does not uncheck the checkbox. Neither does clicking on 'Clear Filters'.
The problem is in your html bindings. so please post this code here.
You using for "IsChecked" variable. This is local scope variable created for each iteration of loop. You not change it from your script code.
Updated html:
<body ng-app="DemoApp" ng-controller="DashboardCtrl">
<div ng-repeat="group in Filters">
<input type="checkbox" value="{{group.title}}" ng-model="CheckboxParent" />
{{group.title}}
<div ng-show="CheckboxParent" class="animate-show" ng-repeat="filter in group.filters">
<input type="checkbox" class="filterChild" value="{{filter.name}}" ng-model="filter.checked" ng-change="ModifyFilter(filter.checked,filter)"/>
{{filter.name}}
</div>
</div>
<div>
<h4>Active Filters</h4>
<p class="clear-filters" ng-click="clearFilters()">Clear Filters</p>
<ul ng-repeat="activeFilter in ActiveFilters">
<li ng-model="activeFilter.checked" ng-click="removeFilter(ModifyFilter(activeFilter.checked,activeFilter))">{{activeFilter.name}}</li>
</ul>
</div>
</body>
Updated script:
var app = angular.module("DemoApp", [])
app.controller("DashboardCtrl", function($scope) {
$scope.clearFilters = function() {
angular.forEach($scope.Filters[0].filters, function(filter) {
filter.checked = false;
});
$scope.ActiveFilters = [];
};
$scope.IsChecked = false;
$scope.ActiveFilters = [];
$scope.ModifyFilter = function (IsChecked, Filter) {
console.log(IsChecked);
if (IsChecked) {
$scope.ActiveFilters.push(Filter);
}
else {
var indexz = $scope.ActiveFilters.indexOf(Filter);
$scope.ActiveFilters.splice(indexz, 1);
}
};
$scope.Filters =
[
{
"title": "Equipment",
"filters": [
{ name: "Rope", checked: false },
{ name: "Cables", checked: false },
{ name: "Dowel", checked: false },
{ name: "Ball", checked: false }
]
}
];
});
Look into my solution on js fiddle: JsFiddle
Related
I am using angularjs I have two list when I click first one I will push the value into another scope and bind the value to second list. Now my requirement is when first list values which are moved to second list, I need to change the color of moved values in list1
Here I attached my fiddle
Fiddle
You can use findIndex and ng-class together to check if the second list contains the same item as first. If present apply css class to the first list item.
JS:
$scope.checkColor = function(text) {
var index = $scope.linesTwos.findIndex(x => x.text === text);
if (index > -1) return true;
else return false;
}
HTML:
<li ng-click="Team($index,line.text)" ng-class="{'change-color':checkColor(line.text)}">{{line.text}}</li>
Working Demo: https://jsfiddle.net/7MhLd/2659/
You can do something like this:
var myApp = angular.module('myApp', []);
function MyCtrl($scope) {
$scope.lines = [{
text: 'res1'
},
{
text: 'res2'
},
{
text: 'res3'
}
];
$scope.linesTwos = [];
$scope.Team = function(index, text) {
var obj = {};
obj.text = text;
$scope.linesTwos.push(obj)
}
$scope.Team2 = function(index, text2) {
$scope.linesTwos.splice(index, 1)
}
$scope.containsObj = function(obj, list) {
var i;
for (i = 0; i < list.length; i++) {
if (angular.equals(list[i], obj)) {
return true;
}
}
return false;
};
}
.clicked {
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
<ul ng-repeat="line in lines">
<li ng-class="{'clicked': containsObj(line,linesTwos)}" ng-click="Team($index,line.text)">{{line.text}}</li>
</ul>
<ul>
<li>__________</li>
</ul>
<ul ng-repeat="line in linesTwos">
<li ng-click="Team2($index,line.text)">{{line.text}}</li>
</ul>
</div>
you have to achieve it using ng-class and create a dynamic class style for pushed data please check my working example fiddle
JS fiddle sample
in HTML nedd to do these changes
<li ng-click="Team($index,line.text,line)" ng-class="{'pushed':line.pushed}">
<li ng-click="Team2($index,line.text,line)">
In css
.pushed{color:red;}
In Controller
`$scope.Team=function(index,text,line){
var obj={};
obj = line;
$scope.linesTwos.push(obj)
line.pushed = true;
}`
`scope.Team2 = function(index,text2,line){
$scope.linesTwos.splice(index,1)
line.pushed = false;
}
`
its because angular two way binding
Is it possible to use shift and mouse click to select multiple elements on a table using AngularJS?
I have a table in which the first column is a checkbox and I would like to use SHIFT key and mouse click in order to select multiple rows continuously and can do things like delete, edit them etc.
Example by steps:
Click on 1st row's checkbox.
Hold down SHIFT key.
Click on 10th row's checkbox.
Result: the first 10 rows will be selected.
Does anyone know how this can be done using AngularJS?
I had a similar requirement. And while it's true that the proper way to update the checkboxes is by directly updating the model I wanted a more general solution.
So I built a pair of directives so I can reuse it on any checkbox list. Basically you wrap all the checkboxes with <multi-checkbox-container> and then add a multi-checkbox attribute to each checkbox. The code does the rest. Simple and easy.
angular
.module('app', [])
.controller('MainController', function($scope) {
var vm = this;
$scope.checks = {};
$scope.botigues = [1, 2, 3, 4, 5, 6];
})
.component('multiCheckboxContainer', {
controller: function () {
var ctrl = this;
var checkboxes = [];
var checkboxModels = [];
var previousClickedCheckbox = null;
ctrl.addCheckbox = addCheckbox;
ctrl.onCheckboxClick = onCheckboxClick;
function addCheckbox(checkbox, checkboxModelCtrl) {
checkboxes.push(checkbox);
checkboxModels.push(checkboxModelCtrl);
}
function onCheckboxClick(checkbox, shiftKey) {
var start, end, i, checking;
if (shiftKey && previousClickedCheckbox) {
checking = checkbox.prop('checked')
start = checkboxes.indexOf(previousClickedCheckbox);
end = checkboxes.indexOf(checkbox);
if (start > end) {
start = start + end;
end = start - end;
start = start - end;
}
for (i = start; i <= end; i++) {
checkboxes[i].prop('checked', checking);
checkboxModels[i].$setViewValue(checking);
}
}
previousClickedCheckbox = checkbox;
}
}
})
.directive('multiCheckbox', function () {
return {
restrict: 'A',
require: ['^^multiCheckboxContainer', 'ngModel'],
link: function (scope, element, attrs, controllers) {
var containerCtrl = controllers[0];
var ngModelCtrl = controllers[1];
containerCtrl.addCheckbox(element, ngModelCtrl);
element.on('click', function (ev) {
containerCtrl.onCheckboxClick(element, ev.shiftKey);
});
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular.min.js"></script>
<div ng-app="app" ng-controller="MainController as vm">
<multi-checkbox-container>
<div ng-repeat="botiga in botigues">
<input type="checkbox" multi-checkbox ng-model="checks[botiga]">
<label>Botiga {{botiga}}</label>
</div>
</multi-checkbox-container>
<p>checks = {{ checks }}</p>
</div>
Not a complete solution, but this should work for you.
http://jsfiddle.net/AvGKj/705/
just keep track of each lastChecked checkbox, and on shift+click, mark all the checkboxes as checked.
<input type="checkbox" ng-checked = 'appObj.checked' ng-click="checked($index, $event)">
$scope.checked = function($index, $event){
if($scope.lastChecked && $event.shiftKey){
for(i=$scope.lastChecked; i<$index;i++){
$scope.myAppObjects[i].checked=true;
}
}
$scope.myAppObjects[$index].checked=true;
$scope.lastChecked = $index;
}
this code would only work if you ckeck from 0 - positive integer , but not reverse, you wuld require to do some modification to make it work completely.
hope this helps
Below presented the solution (Special thanks to Naeem Shaikh):
http://jsfiddle.net/dmakris/AvGKj/709/
HTML code:
<div ng-controller="MyCtrl">
<table class='table table-bordered'>
<tr ng-repeat="obj in myObjects">
<td>{{obj.id}}
<input type="checkbox" ng-checked = 'obj.checked' ng-click="checked($index, $event)">
</td>
<td>test {{obj.id}}</td>
- </tr>
</table>
</div>
Javascript (AngularJS) code:
function MyCtrl($scope) {
$scope.myObjects = [{id: 1, checked:false}, {id: 2, checked:false},
{id: 3, checked:false}, {id: 4, checked:false},
{id: 5, checked:false}, {id: 6, checked:false},
{id: 7, checked:false}];
$scope.checked = function($index, $event){
if(typeof $scope.lastChecked !='undefined' && $event.shiftKey){
for(i=$scope.lastChecked; i<=$index; i++){
$scope.myObjects[i].checked=true;
}
}
$scope.lastChecked = $index;
$scope.myObjects[$index].checked=true;
}
}
I'm working with list of checkboxes and I have next logic behavior for it:
if all items selected, checkbox "select all" is checked
if one of all selected items has been unchecked, checkbox "select all" is unchecked as well
This logic is clear. Depends of what item is checked I extract its id to an additional array and then using this array for request that to get data.
For pushing everything works fine, but for slicing the logic is strange. So I can slice the array until first item is checked, however I unchecked the first item, pushed and sliced items no more related with checkboxes.
I have reproduced plunker with it, so I appreciate if anybody could help me to find what I'm missing.
$scope.modelClass = {
selectedAll: false
};
$scope.selectAllClass = function (array) {
angular.forEach(array, function (item) {
item.selected = $scope.modelClass.selectedAll;
$scope.param =''
});
};
$scope.checkIfAllClassSelected = function (array) {
$scope.modelClass.selectedAll = array.every(function (item) {
return item.selected == true
});
$scope.checked = array.filter(function (item) {
return item.selected == true
}).length;
angular.forEach(array, function (obj) {
if(obj.selected == true){
requestClass(obj)
}
});
};
var selectedClass = [];
var requestClass = function (obj) {
selectedClass.push(obj);
angular.forEach(selectedClass, function (val) {
if (val.selected != true) {
selectedClass.splice(selectedClass.indexOf(val.id), 1);
}
else {
selectedClass = selectedClass.filter(function (elem, index, self) {
return index == self.indexOf(elem);
})
}
});
$scope.param = _.map(selectedClass, 'id')
};
$scope.classes = [
{"id":4,"name":"Achievement","selected":false},
{"id":13,"name":"Information","selected":false},
{"id":6,"name":"Issue","selected":false},
{"id":5,"name":"Message","selected":false},
{"id":9,"name":"Request","selected":false}
]
The logic looks good for me, not sure what's wrong here. I've took the first solution from this post (it looks like you are using the second one) and slightly modified it for your needs.
$scope.model = {
selectedClass : []
}
$scope.isSelectAll = function(){
$scope.model.selectedClass = [];
if($scope.master){
$scope.master = true;
for(var i=0;i<$scope.classes.length;i++){
$scope.model.selectedClass.push($scope.classes[i].id);
}
}
else{
$scope.master = false;
}
angular.forEach($scope.classes, function (item) {
item.selected = $scope.master;
});
$scope.param = $scope.model.selectedClass
}
$scope.isChecked = function() {
var id = this.item.id;
if(this.item.selected){
$scope.model.selectedClass.push(id);
if($scope.model.selectedClass.length == $scope.classes.length ){$scope.master = true;
}
} else {
$scope.master = false;
var index = $scope.model.selectedClass.indexOf(id);
$scope.model.selectedClass.splice(index, 1);
}
$scope.param = $scope.model.selectedClass
}
$scope.classes = [
{"id":4,"name":"Achievement","selected":false},
{"id":13,"name":"Information","selected":false},
{"id":6,"name":"Issue","selected":false},
{"id":5,"name":"Message","selected":false},
{"id":9,"name":"Request","selected":false}
]
html
<div ng-class="{'selected': master, 'default': !master}">
<div>
<input type="checkbox" ng-model="master" ng-change="isSelectAll()" > Select all
</div>
</div>
<div ng-repeat="item in classes | orderBy : 'id'" ng-class="{'selected': item.selected, 'default': !item.selected}">
<div >
<input type="checkbox" ng-model="item.selected" ng-change="isChecked()">
{{ item.name }}
</div>
</div>
this is fixed plunker
This is my code. i am using $localStorage for pushing an object into array. when i clicking the button the object is pushed properly and splicing the same same object again click on the same button. $localStorage.tableArray assign to the $scope.Storage for dropdown list. Drop down list coming good when the button action done.
My problem is the $scope.$storage having two items. if i refresh the page dropdown list not came.
if i pushing or splicing action performed on the buttons drop down list coming good.
please help how to get $scope.$storage items into the dropdown list when refreshing the page.
I Create a plunker regarding this. check once
HTML:
<body ng-controller="MainCtrl">
<a class="btn {{table.btnClass}} btn-success" ng-repeat="table in tablelist" ng-click="getTable(table)" style="padding-left:1px">{{table.tablename}}</a>
<select ng-options="table.tablename as table.tablename for table in $storage" ng-model="table.tablename"><option value="">---select table---</option></select>
JS:
var app = angular.module('plunker', ["ngStorage"]);
app.controller('MainCtrl', function ($scope,$localStorage,$filter) {
$scope.tablelist = [{ "tablename": "t1" }, { "tablename": "t2" },{ "tablename": "t3" },{ "tablename": "t4" }]
if ($localStorage.tableArray === undefined) {
$localStorage.tableArray = []
}
if ($localStorage.tableslist === undefined) {
$localStorage.tableslist = []
}
angular.forEach($scope.tablelist, function (list, $index) {
var found = $filter('filter')($localStorage.tableArray, { tablename: list.tablename }, true);
if (found.length) {
$scope.tablelist[$index].btnClass = found[0].btnClass;
}
});
$scope.getTable = function (table) {
table.btnClass = table.btnClass == "btn-danger" ? "btn-success" : "btn-danger"
var exists = false;
angular.forEach($localStorage.tableArray, function (list, $index) {
if ((list.tablename == table.tablename)) {
console.log(list.tablename)
console.log(table.tablename)
exists = true;
$localStorage.tableArray.splice($index, 1)
$localStorage.tableslist.splice($index, 1)
$scope.$storage= $localStorage.tableArray;
console.log( $scope.$storage)
return false
}
});
if (!exists) {
$localStorage.tableslist.push(table)
$localStorage.tableArray = $localStorage.tableslist;
$scope.$storage = $localStorage.tableArray
console.log($localStorage.tableArray)
table.color = "red"
}
}
});
https://plnkr.co/edit/0RpAGVR5ZpVFMvmmxipu?p=preview
As per my understanding you want your dropdown list to be initialized on refresh with the stored value from your localstorage.
Adding below line in controller works for me:
$scope.$storage = $localStorage.tableArray
Check plnkr
I have a data model that comes in, by default I give the first ticker a selected status of true.
Now when a user clicks another item, I need to efficiently deselect all the others and set the selected value to true for the item clicked:
<li class="ticker-li"
ng-repeat="ticker in tickers"
ng-hide="ticker.removed"
ng-class="{'selected':ticker.selected}"
ng-mouseleave="hideTickerOptions()">
<div class="ticker"
ng-click="unselectAll(); ticker.selected = !ticker.selected;
selectTicker(ticker);">
{{ticker.ticker}}
</div>
</li>
Tried a forEach function here, but with the error [object Array] is not a function:
var vs = $scope;
vs.unselectAll = function() {
vs.tickers.forEach(vs.tickers, function(ticker) {
ticker.selected = false;
});
};
A regular for-loop will work, but is it an efficient way to toggle all the selected values to false?
for (var i = 0; i < vs.tickers.length; i++) {
vs.tickers[i].selected = false;
}
My thinking here is run this unselectAll function to deselect everything, then the next code in the markup which select the current item:
<div class="ticker"
ng-click="unselectAll(); ticker.selected = !ticker.selected;
selectTicker(ticker);">
{{ticker.ticker}}
</div>
I tried to do it using radio inputs.
var app = angular.module('AppForm', []);
app.controller('ctrForm', function ($scope) {
$scope.choices = [
{ id: 'Choice1', check: false },
{ id: 'Choice2', check: false },
{ id: 'Choice3', check: false },
{ id: 'Choice4', check: false },
{ id: 'Choice5', check: false },
{ id: 'Choice6', check: false },
{ id: 'Choice7', check: false }
];
$scope.setDefault = function (item) {
angular.forEach($scope.choices, function (p) {
p.check = false; //set them all to false
});
item.check = true; //set the clicked one to true
};
});
.selected {
background-color: yellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.21/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div ng-app="AppForm" ng-controller="ctrForm">
<ul>
<li style="list-style:none" ng-class="{'selected':item.check}" ng-repeat="item in choices"><input type="radio" name="group" ng-model="item.check" ng-click="setDefault(item)" value="true" />{{item.id}}...{{item.check}}</li>
</ul>
</div>
The foreach wouldn't be less efficient than anything angular could do 'for free'. Either way it'll have to set the others as unselected..
What'd I'd propose instead would be to have a single thing "selectedItem" and a set of things "items".
then you can 'say'
<li class="ticker-li"
ng-repeat="ticker in tickers"
ng-hide="ticker.removed"
ng-class="{'selected':ticker == selectedTicker}"
ng-mouseleave="hideTickerOptions()">
<div class="ticker" ng-click="selectedTicker = ticker">
{{ticker.ticker}}
</div>
</li>
you could then access selectedTicker to get it's properties
<div>{{selectedTicker.name}}</div>
If your set on using ticker.selected, you can use a jquery .each loop to unselect all of them.
$scope.selectTicker = function(ticker)
{
//deselect all tickers
$.each(tickers, function() { this.selected = false; });
//select the ticker you passed in
ticker.selected = true;
}
and in your view:
<div class="ticker"ng-click="selectTicker(ticker);">
{{ticker.ticker}}
</div>