In table, get selected row id in array - angularjs

In table every row assosiated with checkbox and have option to check all row.
I want to get selected rows id of table in array.
Here is plunker code.
HTML:
<table id="datatable-buttons" class="table table-striped table-bordered">
<thead>
<th>
<input type="checkbox" ng-model="selectRowId" ng-click="selectedAll()">
</th>
</thead>
<tbody ng-init="get_product()">
<!--step 6-->
<tr ng-repeat="product in filtered = (pagedItems| filter:search | orderBy : predicate :reverse) | startFrom:currentPage * entryLimit | limitTo:entryLimit | findobj:multipleVlaue | searchFor:searchString"> <!-- searchFor:searchString -->
<td>
<input type="checkbox" ng-model="selctedIds[product.id]" ng-checked="product.deleted">
</td>
</tr>
</tbody>
</table>
Controller:
$scope.selectedAll = function () {
$scope.pagedItems.forEach(function (product) {
if ($scope.selectRowId) {
product.deleted = true;
} else {
product.deleted = false;
}
});
}

If you want something scalable that accommodates things like complex filtering, pagination, etc. then I suggest you write an angular property to each object. So for the checkbox we'd want to toggle this boolean value like so:
<input type="checkbox" ng-model="item.$selected"/>
For your toggle all/none, you'll need to tap a controller function:
$scope.toggleAll = function(bSelect){
itemArray.forEach( function(item){ item.$selected = bSelect; })
}
The reason I suggest prepending your selected value with a $ like $selected is that any HTTP calls you make with the objects, Angular will strip any $property before converting to JSON, just in case your backend has issue.
I'd recommend using a filter to pull the IDs:
<div>{{ itemArray | getSelIds }}</div>
and the filter
.filter( 'geSeltIds', function(){
return function(items){
//if you happen to use lodash
return _.chain(items).filter({$selected:true}).map('id').value()
//manual
ids = []
items.forEach(function(item){
if(item.$selected)
ids.push(item.id)
})
return ids
}
})

This filter is cleaner:
.filter( function (item) {
return item.$selected;
}).map(function (item) { return item.id });

Related

Angular Filter based on Multiselect-Dropdown

I use nya-bootstrap-select directive (http://nya.io/nya-bootstrap-select/)
for a Multiselect-Dropdown ( Angular 1.5.8 ).
Now I would like to filter a collection based on the selected options.
Example:
https://jsfiddle.net/mrtzdev/2z6xfo5w/18/
<ol id="dynamic-options" class="nya-bs-select" ng-model="model2" multiple >
<li nya-bs-option="(key,value) in companyList" >
<a>{{ value.name}}</a>
</li>
</ol>
Filtered Collection:
<tbody>
<tr ng-repeat="client in clients | filter:{ name: model1.name, company: { name: model2.name } } ">
<td>{{$index + 1}}</td>
<td><em>{{client.name}}</em>
</td>
<td>{{client.designation}}</td>
<td>{{client.company.name}}</td>
</tr>
</tbody>
This obviously does not work for the multiselect. How can use a custom filter, to filter on multi-selected options ?
I modified your fiddle and make it work. This filter is not good in dynamic handling but it will allow you to filter your data by the exact filter attribute name.
View
<tr ng-repeat="client in clients | filter:{ name: model1.name} | inArrayExact : { myArray: model2, searchKey: 'name', filterKey: 'company' }">
<td>{{$index + 1}}</td>
<td><em>{{client.name}}</em>
</td>
<td>{{client.designation}}</td>
<td>{{client.company.name}}</td>
</tr>
AngularJS custom filter
App.filter('inArrayExact', function($filter){
return function(list, arrayFilter, element){
if((angular.isArray(arrayFilter.myArray) && arrayFilter.myArray.lenght > 0) && || angular.isObject(arrayFilter.myArray)){
var itemsFound = {};
angular.forEach(list, function (listItem, key) {
angular.forEach(arrayFilter.myArray, function (filterItem) {
if (angular.isDefined(filterItem[arrayFilter.searchKey])
&& angular.isDefined(listItem[arrayFilter.filterKey])
&& angular.isDefined(listItem[arrayFilter.filterKey][arrayFilter.searchKey])) {
if (angular.isUndefined(itemsFound[key])
&& listItem[arrayFilter.filterKey][arrayFilter.searchKey] == filterItem[arrayFilter.searchKey]) {
itemsFound[key] = listItem;
}
}
});
});
return itemsFound;
} else {
return list;
}
};
});
model2 is an array objects not a string, you need to create a custom filter where you pass model2 and loop over the objects and check the name.
you can check this link on how to build custom filters
https://toddmotto.com/everything-about-custom-filters-in-angular-js/

Counting selected checkbox in AngularJS

I'm having a hard time counting selected checkboxes in my application. I've tried following along some other stack overflow questions but no dice yet...if you guys have any experience with counting checkboxes, some help would be great.
HTML:
<div class="row">
<div class="col-md-12">
<table id="document-table" st-table="documents" st-safe-src="yourDisplayedCollection" class="table">
<div>Total checked: ({{selectedCounter}})</div>
<thead>
<tr>
<th>
<st-select-all all="yourDisplayedCollection"></st-select-all>
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="document in documents">
<td><input type="checkbox" ng-model="document.isSelected"/></td>
</tr>
</tbody>
</table>
</div>
</div>
Controller:
.controller('DocumentsController', /** #ngInject */ function ($scope, restData, dateFormats, documents) {
$scope.dateFormat = dateFormats.angularDateFilter;
$scope.documents = documents.resultBag[0].documentBag;
$scope.yourDisplayedCollection = [].concat(documents.resultBag[0].documentBag);
$scope.selectAll = function (selected) {
var documents = $scope.documents;
angular.forEach(documents, function (documents) {
documents.selected = selected;
});
// Update the counter
if(selected){
$scope.selectedCounter = documents.length;
} else {
$scope.selectedCounter = 0;
}
};
EDIT:
I have a check all boxes checkbox at the top which is why i have the yourDisplayedCollection in the table as well as the ng-model="document.isSelected"
You need to rework a couple things if I am understanding the anticipated outcome correctly.
First(html):
<tr ng-repeat="document in documents">
//Bind your model directily to the selected property in your object (document)
<td><input type="checkbox" ng-model="document.selected"/></td>
</tr>
Second:
$scope.selectAll = function (selected) {
var documents = $scope.documents;
angular.forEach(documents, function (doc) {
if(doc.selected)
$scope.selectedCounter +=1;
});
};
This will give you a correct count everytime. Though your function naming is misleading. SelectAll should mean literally select all. To me it looks like your just counting.
Simplest way to do this is use Array.prototype.filter() and use length of filtered array
<input type="checkbox" ng-model="document.selected"/>
And for counter:
$scope.selectedCounter = $scope.documents.filter(function(item){
return item.selected;
}).length;
Need to be aware that you are breaking the golden rule of always using an object in ng-model.
ng-repeat creates a child scope and when you use a primitive in the child scope the parent controller can't see it change

Stuck on angularjs ng-checked

I'm trying to implement that when a user clicks a check box it displays all products in the ng-repeat with a quantity of 0. Else when the check box is not check all items display. Currently I was able to get half the functionality.
Check box :
<input type="checkbox" name="onoffswitch" class="onoffswitch-checkbox" id="myonoffswitch" ng-checked="vm.OnHandQty()">
Table
<tr ng-repeat="item in vm.items | filter :search">
<td ng-bind="item.itemNo"> </td>
<td ng-bind="item.description"></td>
<td ng-bind="(item.listPrice | currency)"></td>
<td ng-bind="item.onHandQty" ng-model="quantity"></td>
</tr>
Controller
vm.OnHandQty = function () {
$scope.search = {};
vm.items.forEach(i => {
if (i.onHandQty == 2) {
console.log(i);
$scope.search = i;
return true;
}
else {
$scope.search =i;
return false;
}
});
}
I would propose changing the implementation of your checkbox and controller:
Checkbox
<input type="checkbox" ng-model="vm.checked" name="onoffswitch" class="onoffswitch-checkbox" id="myonoffswitch">
- Here, we use "ng-model" instead of "ng-checked" and "vm.checked" is a variable that you define as the ng-model for your checkbox.
Controller
$scope.search = function(item) {
return ($scope.vm.checked) ? item.onHandQuantity === 0: true;
};
- Here, we define the "ng-repeat" filter that you are using in your table.
Try this instead:
<tr ng-repeat="item in vm.items" ng-show="onoffswitch==true && item.onHandQty != 0? false : true">
<td ng-bind="item.itemNo"> </td>
<td ng-bind="item.description"></td>
<td ng-bind="(item.listPrice | currency)"></td>
<td ng-bind="item.onHandQty" ng-model="quantity"></td>
</tr>
This will only show the row if onoffswitch is true and if the onHandQty is zero, otherwise it will show the row. So the row will be hidden if onoffswitch is true and onHandQty is not zero.
You can make use of ng-change and ng-model.
<input type="checkbox" name="onoffswitch" class="onoffswitch-checkbox" id="myonoffswitch" ng-model="vm.checked" ng-change="checkBoxChange(vm.checked)">
Then, from you checkBoxChange function, apply your business logic:
vm.checkBoxChange = function(checked){
if(checked){
//Do something
}else{
//Something else
}
};

How to change $index for two ngRepeats with same input but different filters?

I've simulated my problem here.
Looking into this html, you can see that I am doing two ng-repeats with the same array as input, but different filters to each one:
<div ng-app='Lists'>
<div ng-controller='listsController'>
<table>
<tbody>
<tr ng-repeat='item in listValues | filter : xxx track by $index' ng-click="update($index)">
<td>{{item.ref}}</td>
<td>{{item.others}}</td>
</tr>
</tbody>
</table><hr/>
<table>
<tbody>
<tr ng-repeat='item in listValues | filter : yyy track by $index' ng-click="update($index)">
<td>{{item.ref}}</td>
<td>{{item.others}}</td>
</tr>
</tbody>
</table><hr/>
<div>{{updateIndex}}</div>
</div>
</div>
And my js code:
var appModule = angular.module('Lists', []);
appModule.controller('listsController', function($scope) {
$scope.listValues = [
{'ref' : '1', 'others' : 'abc..'},
{'ref' : '2', 'others' : 'def..'},
{'ref' : '1', 'others' : 'ghi..'},
{'ref' : '2', 'others' : 'jkl..'}
];
$scope.xxx = function(a){
return a.ref == 1;
};
$scope.yyy = function(a){
return a.ref == 2;
};
$scope.update = function(i) {
$scope.updateIndex = i;
};
$scope.updateIndex = "none";
});
The problem I'm stuck is that the update(index) function needs to change the object in the correct index of the listValues array. But as you can see clicking in the object of the second table gives me the $index of the first table.
How to work around this situation? Thanks in advance.
Using the $index is doomed to fail, even if you iterate once. $index is the index of the current item in the filtered array. And that index is different from the index of the same element in the original, non-filtered array.
If you want to modify an item on click, don't pass its index as argument. Pass the item itself:
ng-click="update(item)"
Instead of filters use ng-if which allows you to track items by index.Index will give exact click even list has duplicate items
<body>
<div ng-app='Lists'>
<div ng-controller='listsController'>
<table>
<tbody>
<tr ng-repeat="item in listValues track by $index" ng-click="update($index)" ng-if="xxx(item)=='1'">
<td>{{item.ref}}</td>
<td>{{item.others}}</td>
</tr>
</tbody>
</table><hr/>
<table>
<tbody>
<tr ng-repeat='item in listValues track by $index' ng-click="update($index)" ng-if="item.ref=='2'">
<td>{{item.ref}}</td>
<td>{{item.others}}</td>
</tr>
</tbody>
</table><hr/>
<div>{{updateIndex}}</div>
</div>
</div>
</body>

Sorting array in asc desc

I am new to angularjs here is my code i want to get data from url and also sort it by dynamically by selecting an item from select element but could't get the required result please help me out
Html
<tr ng-repeat="x in names | orderBy: sortBy ">
<td><a ng-href="{{ x.data.url}}">{{x.data.title}}</a>
</td>
<td>{{x.data.score}}</td>
</tr>
Code
$scope.$watch(function () {
return $scope.sortExpression
}, function (newSort) {
$scope.sortBy = 'data.' + $scope.sortExpression
})
$http.get("https://www.reddit.com/r/worldnews/new.json")
.success(function (response) {
$scope.names = response.data.children
})
Fiddle
https://jsfiddle.net/rr6q0umb/1/
Add input for the direction
<label><input type="checkbox" ng-model="direction">Reverse</label>
Add to your orderBy filter the direction value (true for reverse)
<tr ng-repeat="x in names | orderBy:sortBy:direction">

Resources