Keep selected element highlighted after resorting table - javascript

I have a table in AngularJS with several columns that can each be sorted ascending and descending. I want a row to be selected whenever a user clicks on it. I do this by getting the selected index of the table. However, once I resort one of the columns, the selected row remains highlighted. What I want to do is to keep the previously selected item highlighted...whereever its new index may be after the resorting. Here is a code snippet:
My table body:
<tbody>
<tr
ng-class="{'selected':$index == list.selectedRow}"
ng-repeat="item in list.itemList | order:list.orderBy:list.orderAsc">
<td ng-click="list.select(item);list.setClickedRow($index)">{{ item.number }}
</td>
<td ng-click="list.select(item);list.setClickedRow($index)">{{ item.name }}
</td>
</tr>
</tbody>
The method for setting the selected row:
function setClickedRow(index) {
vm.selectedRow = index;
}

Based on Slonski answer, I suggest you to loop over all items to set selected = false when you change your selection:
function setClickedRow(item) {
for(var i = 0; i < $scope.list.itemList.length; i++) {
if(item == $scope.list.itemList[i]) item.selected = true;
else $scope.list.itemList[i].selected = false;
}
item.selected = true;
}
Update: Solution without a loop
var myApp = angular.module('myApp', []);
myApp.controller('MyCtrl', ['$scope', function($scope) {
$scope.setMaster = function(section) {
$scope.selected = section;
}
$scope.isSelected = function(section) {
return $scope.selected === section;
}
}]);
.active {
background-color: orange;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
<table>
<tr ng-repeat="i in ['One', 'Two', 'Three']" ng-class="{active : isSelected(i)}">
<td ng-click="setMaster(i)">{{i}}</td>
</tr>
</table>
<hr> {{selected}}
</div>

You can add selected to your item, and the set it to true on click (or set it to !item.selected if you want to toggle selection on click)
<tbody>
<tr
ng-class="{'selected':item.selected}"
ng-repeat="item in list.itemList | order:list.orderBy:list.orderAsc">
<td ng-click="list.select(item);list.setClickedRow(item)">{{ item.number }}
</td>
<td ng-click="list.select(item);list.setClickedRow(item)">{{ item.name }}
</td>
</tr>
</tbody>
function setClickedRow(item) {
item.selected = true;
}

Related

How do i filter name in ng-repeat angularjs?

Currently, if I filter, the BookingID and Product I see that filtered result in UI. How do I have to add a filter for a name? because this name is coming from another array and getting it based on id
need to add filter based on BookingID, Product and name fields
Here's my code:
<div ng-app="datatable" ng-controller="datacontroller">
<md-card>
<div layout="row" style="height:50px; vertical-align: middle;">
<md-input-container md-no-float class="md-block" flex="85" >
<input ng-model="searchBooking" type="text" placeholder="Search">
</md-input-container>
</div>
</md-card>
<md-table-container>
<table md-table>
<thead md-head md-order="filter">
<tr md-row>
<th md-column><span>BookingID</span></th>
<th md-column><span>Product</span></th>
<th md-column><span>Name</span></th>
</tr>
</thead>
<tbody md-body>
<tr md-row ng-repeat="row in filterBooking() | orderBy:filter">
<td md-cell>{{row.BookingID}}</td>
<td md-cell>{{row.Product}}</td>
<td>
<md-select ng-model="row.UserID" ng-change="test(row)">
<md-option ng-repeat="user in users" ng-value="user.id">{{user.name}}</md-option>
</md-select>
</td>
</tr>
</tbody>
</table>
</md-table-container>
</div>
controller
angular.module("datatable", ['ngRoute', 'ngMaterial', 'md.data.table']).controller("datacontroller", ['$scope', function($scope) {
$scope.bookings = [
{
"BookingID":1,
"Product":"test",
"Shop":"A",
"ContactNumber":124,
"UserID":1
},
{
"BookingID":2,
"Product":"bgh",
"Shop":"d",
"ContactNumber":345,
"UserID":2
}
];
$scope.users = [
{
"id":1,
"name":"abc"
},
{
"id":2,
"name":"xyz"
}
]
$scope.searchBooking = '';
$scope.filterBooking = function () {
return $scope.bookings.filter(function (item) {
return (
item.BookingID.toString().indexOf($scope.searchBooking) > -1||
( item.Product.toLowerCase().indexOf($scope.searchBooking.toLowerCase()) > -1)
);
});
};
}]);
demo
Please advice
user name comes from a different array so I'm not sure how should filter name
so if you first add a 'name' property to every object in your bookings array, having its value cross matched from your 'users' array, this will make your life easier as you can then filter like:
<tr md-row ng-repeat="row in filterBooking() | orderBy:'+name'">
'name' being the new property in each of your objects, and + indicating an ascending order.
Adding the 'name' property to the items of your bookings array can be done with a simple for loop.
for (var i=0; i<$scope.bookings.length; i++) {
$scope.bookings[i].name = $scope.users.filter(function(_){ _.id === $scope.bookings[i].UserID })[0].name;
}

Selected all rows with checkbox but for multiple tables displaying with a loop

In my application, I have several tables that are built with a loop.
<div v-for="(dimension, index) in listQuestions" :key="index" :header="`${dimension.name}`">
<table class="table-questions" >
<thead>
<tr>
<th><input type="checkbox" #click="onClickCheckAll(dimension)" /></th>
<th>Sous-dimension</th>
<th>Item</th>
</tr>
</thead>
<tbody v-for="(question,i) in dimension.sousDimensions" >
<tr v-for="(item, p) in question.questions">
<td v-if="item.barometre"><input type="checkbox" checked disabled :id="'choice-' + item.id"/></td>
<td v-else ><input type="checkbox" #click="onClickOneCheckbox(item.id)" :id="'choice-' + item.id" /> </td>
<td style="width: 40%">{{question.name}}</td>
<td >{{item.item}}</td>
</tr>
</tbody>
</table>
</div>
I would like to be able to select all the rows of each table with a checkbox.
I have seen this tuto: vuejs tables and select all checkbox which seems to me very good. But I can’t apply it in my case of several tables.
How can I use the data selected and selectAll like in the example but for several tables?
I have started to build a function to access the items like this and I have my ID of items :
EDIT.
I try to do this :
onClickCheckAll(value) { //when click to all chekckbox
console.log("click")
console.log(value)
console.log(value.sousDimensions)
for (var sousdim of value.sousDimensions)
{
for (var item of sousdim.questions)
{
console.log(this.selectCheck)
const p = this.selectCheck.indexOf(item.id) //looking for index for each item
const checkboxItem = document.querySelector("#choice-" + item.id) //all inputs with id choice-ID and then add or remove "checked" attribute
if (p > -1) { //if still there, delete
this.selectCheck.splice(p, 1);
if (!item.barometre)
{
checkboxItem.checked=false
}
}
else { //if not, adding in array
this.selectCheck.push(item.id)
checkboxItem.checked=true
}
}
}
},
onClickOneCheckbox(val) {
const index = this.selectCheck.indexOf(val);
if (index > -1) //delete item if still in the array
{
this.selectCheck.splice(index, 1);
}
else
{
this.selectCheck.push(val)
}
console.log(this.selectCheck)
}
And it's partially works : when I click individually on the first two rows of my table and then click on the checkbox to select all, all rows get selected...Except the first two!
See the problem here : https://jsfiddle.net/chtouk/rc80ksno/35/
Thanks for help

ng-class doesn't work properly for selected checkbox

I faced with a small problem related with ng-class. I have a list of checkboxes. For this list, I setup ng-class next way, if checkbox selected, set custom css class for selected item. Also I have a checkbox "Select All ", if I click on this box, css class applied for all items, but when I deselect all, css class doesn't change for items which been selected manually before.
I created plunker to show my problem.
What am I missing and where is my mistake? Thanks in advance.
html
<table class="table table-hover">
<tr ng-class="{'selected': allCategoriesSelected, 'default': !allCategoriesSelected}">
<td class="col-md-2">
<input type="checkbox" ng-click="selectAllCategories()" >
</td>
<td class="col-md-10" ng-if="!allCategoriesSelected">Select all</td>
<td class="col-md-10" ng-if="allCategoriesSelected">Deselect all</td>
</tr>
<tr ng-repeat="category in categories | orderBy : 'id'" ng-class="{'selected': allCategoriesSelected, 'default': !allCategoriesSelected}" >
<td class="col-md-2">
<input type="checkbox" ng-model="allCategoriesSelected" ng-click="updateCategory(category.id)">
</td>
<td class="col-md-10">{{ category.name }}</td>
</tr>
</table>
js
$scope.selectedCategories = [];
$scope.allCategoriesSelected = false;
$scope.selectAllCategories = function() {
$scope.allCategoriesSelected = !$scope.allCategoriesSelected;
};
$scope.updateCategory = function(categoryId) {
if ($scope.selectedCategories.indexOf(categoryId) > -1) {
$scope.selectedCategories.splice($scope.selectedCategories.indexOf(categoryId), 1);
} else {
$scope.selectedCategories.push(categoryId);
}
};
Take a look at this plunker, it should work.
This is the controller :
$scope.selectAllCategories = function () {
if(!$scope.allCategoriesSelected) $scope.setAll(false);
else $scope.setAll(true);
};
$scope.updateCategory = function () {
if($scope.checkedAll()) $scope.allCategoriesSelected = true;
else $scope.allCategoriesSelected = false;
};
$scope.checkedAll = function(){
var ret = true;
$scope.categories.forEach(function(item){
if(!item.selected) ret = ret && false;
});
console.log(ret);
return ret;
}
$scope.setAll = function(state){
$scope.categories.forEach(function(item){
item.selected = state;
});
}
I think you are making it too complicated. This can be easily solved with much less code. Here is a working plunker: https://plnkr.co/edit/xJz8pdRa4CBWUbdeYbyk?p=preview
Instead of trying to make a separate array to keep track of selected items, just set selected property on categories array.
<table class="table table-hover">
<tr ng-class="{'selected': allCategoriesSelected, 'default': !allCategoriesSelected}">
<td class="col-md-2">
<input type="checkbox" ng-model="allCategoriesSelected" ng-click="selectAllCategories()" >
</td>
<td class="col-md-10" ng-if="!allCategoriesSelected">Select all</td>
<td class="col-md-10" ng-if="allCategoriesSelected">Deselect all</td>
</tr>
<tr ng-repeat="category in categories | orderBy : 'id'" ng-class="{'selected': category.selected}" >
<td class="col-md-2">
<input type="checkbox" ng-model="category.selected">
</td>
<td class="col-md-10">{{ category.name }}</td>
</tr>
</table>
Changing the markup above, allows this to be accomplished with only one method.
$scope.allCategoriesSelected = false;
$scope.selectAllCategories = function () {
var selected = $scope.allCategoriesSelected ? true : false;
angular.forEach($scope.categories, function(category) {
category.selected = selected;
});
};

AngularJS, CSS : Highlighting a particular table row

is there any way to highlight a particular table row?
I have a table and a set if angular codes for example for example:
angular.module('myApp', []).controller('myTest', function($scope) {
var data = [];
for(var i = 0; i < 10; i++) {
data[i] = i;
}
$scope.data = data;
});
HTML:
<table ng-app="myApp" ng-controller="myTest">
<tr ng-repeat="x in data">
<td > {{ x }} </td>
</tr>
</table>
http://jsfiddle.net/omarjmh/Lvc0u55v/1895/
Is there anyway to do it like
if x is equal to 1
then
css:highlight tr: blue
?
Thanks!
you can use $even and $odd for this.
angular.module('myApp', []).controller('myTest', function($scope) {
var data = [];
for(var i = 0; i < 10; i++) {
data[i] = i;
}
$scope.data = data;
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app = "myApp">
<div ng-controller="myTest">
<table >
<tr ng-repeat="x in data" ng-style="{'background-color': ($even ? 'green' : 'red')}">
<td > {{ x }} </td>
</tr>
</table>
</div>
</div>
use ngStyle:
tr ng-repeat="x in data" ng-style="{'background-color': (x === 1 ? 'blue' : 'white')}"
You can achieve it by using CSS,
tr:nth-child(even) {
background-color: #000000;
}
even/odd both works.
Or with angular,
You should be using the angular directives ngClassEven and ngClassOdd for this.
Have a look at the documentation section for how to use them
http://docs.angularjs.org/api/ng.directive:ngClassEven
http://docs.angularjs.org/api/ng.directive:ngClassOdd

How to use checkbox to filter results with Angular?

I am trying to apply a filter using checkboxes.
The checkboxes are shown correctly:
<div data-ng-repeat="cust in customers">
<input type="checkbox" data-ng-model="search.city" data-ng-true-value="{{ cust.city }}" data-ng-false-value=""/> {{ cust.city }}
</div>
but when checking any checkbox, nothing happens:
<table>
<!-- table heading goes here -->
<tbody>
<tr data-ng-repeat="customer in customers | filter : search">
<td >
{{ customer.firstName }}
</td>
<td >
{{ customer.lastName }}
</td>
<td >
{{ customer.address }}
</td>
<td >
{{ customer.city }}
</td>
</tr>
</tbody>
</table>
The table shows all the customers.
What I want to achieve is: when one or more checkboxes are checked, the table has to show only these rows which match the condition of the checked checkboxes.
What do I have to do to get this working?
You can pass a function to the AngularJS filter. For example:
Set you input tag as:
<input type="checkbox" ng-model="search[cust.city]" /> {{ cust.city }}
Set your filter as:
<tr data-ng-repeat="customer in customers | filter:searchBy() ">
In your controller:
function ctrl($scope) {
$scope.customers = [...];
$scope.search = {};
$scope.searchBy = function () {
return function (customer) {
if ( $scope.search[customer.city] === true ) {
return true;
}
}
};
}
If you wish to show all customer at startup, simply initialise $scope.search with city from the customers array.
Here is a sample Plunker.
It looks like you are providing a list of customers, and when one or more is selected, display a table of customers that are in the same city as those customers that are selected.
To do this, you will need a custom filter:
// Define our filter
app.filter('selectedCustomerCities', function($filter) {
return function(customers) {
var i, len;
// get customers that have been checked
var checkedCustomers = $filter('filter')(customers, {checked: true});
// Add in a check to see if any customers were selected. If none, return
// them all without filters
if(checkedCustomers.length == 0) {
return customers;
}
// get all the unique cities that come from these checked customers
var cities = {};
for(i = 0, len = checkedCustomers.length; i < len; ++i) {
// if this checked customers cities isn't already in the cities object
// add it
if(!cities.hasOwnProperty(checkedCustomers[i].city)) {
cities[checkedCustomers[i].city] = true;
}
}
// Now that we have the cities that come from the checked customers, we can
//get all customers from those cities and return them
var ret = [];
for(i = 0, len = customers.length; i < len; ++i) {
// If this customer's city exists in the cities object, add it to the
// return array
if(cities[customers[i].city]) {
ret.push(customers[i]);
}
}
// we have our result!
return ret;
};
});
Your markup will then change into something like this:
<div data-ng-repeat="customer in customers">
<!-- record that this customer has been selected -->
<input type="checkbox" ng-checked="customer.checked" ng-model="customer.checked" /> {{ customer.city }}
</div>
<table>
<!-- table heading goes here -->
<tbody>
<!-- use our custom filter to only display customers from the cities selected -->
<tr data-ng-repeat="customer in customers | selectedCustomerCities">
<td>{{ customer.firstName }}</td>
<td>{{ customer.lastName }}</td>
<td>{{ customer.address }}</td>
<td>{{ customer.city }}</td>
</tr>
</tbody>
</table>
You can see it working at this Plunker: http://plnkr.co/edit/GlHRLKECR4jeBS7Vf7TX?p=preview

Categories

Resources