Angular ng-repeat stay paged after filter - angularjs

I'm using AngularJS and I have a simple table using ng-repeat and filter. When i insert anything at the search input it filters OK but it keeps paginated as it was before I filter the table. Any ideas why this is happening ?
Here's my code:
//some var initialization
$scope.pagina = {};
$scope.pagina.currentPage = 1,
$scope.pagina.numPerPage = 10,
$scope.pagina.maxSize = 5;
//return from server with data
coresFactory.getCores().then(function(response) {
$scope.tabelaCores = response.data;
$scope.filteredTodos = $scope.tabelaCores.cores.slice(0, 10);
});
//do pagination
$scope.$watch('pagina.currentPage', function() {
var begin = (($scope.pagina.currentPage - 1) * $scope.pagina.numPerPage),
end = begin + $scope.pagina.numPerPage;
$scope.filteredTodos = $scope.tabelaCores.cores.slice(begin, end);
},true);
<input ng-model="pesquisaTabela" type="search" style="width:300px;" class="form-control input-inline" placeholder="" aria-controls="sample_1"></label>
<table class="table" style="margin-bottom:5px;border:1px solid #DDDDDD" id="sample_1">
<thead>
<tr style="background-color:#F9F9F9">
<th style="width:100px; text-align:center;"> Id </th>
<th> Nome </th>
<th> Plural </th>
<th style="width:100px; text-align:center;"> Ativo </th>
</tr>
</thead>
<tbody>
<tr ng-repeat="cor in filteredTodos | filter:pesquisaTabela" ng-click="setSelected(cor.id)" ng-class="{linhaSelected: cor.id === idCorSelecionada}">
<td style="text-align:center;"> {{cor.id}} </td>
<td style="text-transform:capitalize"> {{cor.nome}} </td>
<td style="text-transform:capitalize"> {{cor.plural}} </td>
<td style="text-align:center;">
<span ng-if="cor.status=='sim'" class="label label-sm label-success"> Sim </span>
<span ng-if="cor.status=='nao'" class="label label-sm label-danger"> Não </span>
</td>
</tr>
</tbody>
</table>
<pagination first-text="<<" last-text=">>" next-text=">" previous-text="<" ng-model="pagina.currentPage" total-items="tabelaCores.cores.length" max-size="pagina.maxSize" boundary-links="true"></pagination>

You have quite a disconnect between various parts
Pagination is working off of one array, display from another and filter from yet another because when filter kicks in it returns a new filtered array.
The way you have things structured, your filter won't work properly either.
When you slice the main data array the filter is only going to work on that part that is sliced....not the whole main array
In order for pagination to be synchronized with filtering your simplest start point would likely be do your own filtering and share the same filtered array between the pagination and the table.
There are some other built in filters that you could use also like limitTo that takes 2 arguments limit and begin. That would help you get rid of currrent slice
There are lots of available grid/table directives available.
Using one of those would be my best suggestion
There is one other way you could do this all in the view. There is a syntax for ng-repeat that creates a new filtered array on the scope and therefore gives you access to it's length
<tr ng-repeat="row in filteredData = ( data |filter:pesquisaTabela | limitTo:10:start)">
Using this you could pass filteredData array to the total-items of the pagination directive.
It also now lets you do things like:
<div> Filtered length is: {{filteredData.length}}</div>

Related

ng repeat dynamic with key objet json AngularJS

I have a small problem I would like to set up a ng-repeat dynamic with the values I receive from my JSON object,
First, i made my th from my table with the keys
Secondly, i would like to do my td in dynamic (without putting the name of the key ex: obj.NOM, obj.TYPE ...)
I managed to do something with an Object.keys but logic is not good so I need some help
this is my JSON object ( i show you just the little piece of code that I have a problem )
"HEADER":[
{"NOM":"API-APP","TYPE":"string","DESCRIPTION":"Code application"},
{"NOM":"API-SIGNATURE","TYPE":"string","DESCRIPTION":"Signature de la requete API"},
{"NOM":"API-TIMESTAMP","TYPE":"integer","DESCRIPTION":"Timestamp en microseconde"}]
and this is my ng repeat
<span><b>HEADER</b></span>
<br>
<br>
<table class="table">
<th ng-repeat ="(key, itemHeader) in itemHead.HEADER[0] track by $index">{{key}}</th>
<tr ng-repeat ="(key, itemHeader) in itemHead.HEADER track by $index" >
<td>{{getFirstPropertyValue(itemHeader,$index)}}</td>
</tr>
</table>
I explain i made first a ng-repeat for th with the keys and I would like put my data (3 data per row) in td without put ( .NOM .TYPE .DESCRIPTION)
So I took the function object.key which works very well but that makes me just one element per row but I need 3 elements per row
this is my scope for the function object.key
$scope.getFirstPropertyValue = function(obj,index){
return obj[Object.keys(obj)[index]];
}
and this my result
thanks in advance for your help
<table class="table">
<thead>
<tr>
<th ng-repeat="(key, itemHeader) in itemHead.HEADER[0]">
{{key}}
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in itemHead.HEADER">
<td ng-repeat="column in row">
{{column}}
</td>
</tr>
</tbody>
</table>

ng-repeat shows terrible performance with large lists

I'm experiencing performance issues when using ng-repeat for long lists (thousands of records) that need to be shown within a table.
Here is the HTML I'm using:
<table class="table table-hover">
<thead>
<tr>
<th ng-repeat="One_Header in Data_List.Header track by $index">{{One_Header}}</th>
</tr>
</thead>
<tbody>
<tr ng-model="Data_List" ng-repeat="One_Source in Data_List.Body track by $index" style="cursor:pointer">
<td ng-repeat="One_Data_Field in One_Source track by $index">{{One_Data_Field}}</td>
</tr>
</tbody>
</table>
The received JSON (takes about 1 second to get it from the server) contains the data as follows:
"Data":{
"Header":["Title_1","Title_2","Title_3"],
"Body":[
["Rec_1_Data_1","Rec_1_Data_2","Rec_1_Data_3"],
["Rec_2_Data_1","Rec_2_Data_2","Rec_2_Data_3"],
["Rec_3_Data_1","Rec_3_Data_2","Rec_3_Data_3"],
:
["Rec_n_Data_1","Rec_n_Data_2","Rec_n_Data_3"]
]
}
I also tried one-directional binding (i.e. {{::One_Data_Field}}) without any noticeable improvement.
As stated above, response arrives within a second and then it takes up to 10 seconds for the table to be built.
in order to improve the performance, you can use pagination directives created using angular js.
Angular-Paging
pagination
If you are using Angular material design then I would highly recommend using virtual repeat
virtual repeat
you can try this sample pagination implementation:
var pageSize = 15;
$scope.paginationLimit = function(pagesShown) {
return pageSize * pagesShown.count;
};
$scope.hasMoreItemsToShow = function(list, pagesShown) {
return pagesShown.count < (list.length / pageSize);
};
$scope.showMoreItems = function(pagesShown) {
pagesShown.count = pagesShown.count + 1;
};
<tr ng-model="Data_List" ng-repeat="One_Source in Data_List.Body track by $index " style="cursor:pointer">
<td ng-repeat="One_Data_Field in One_Source track by $index | limitTo: paginationLimit(pagesShown)">{{One_Data_Field}}</td>
</tr>
//sample row with show more button
<tr class="showMore">
<td></td>
<td class="showBtn">
<button type="button" class="btn btn-primary btn-lg" ng-init="pagesShown={'count': 1}" ng-click="showMoreItems(pagesShown)" ng-show="hasMoreItemsToShow(One_Source track, pagesShown)">Show More</button>
</td>
<td></td>
</tr>

Angular orderBy and scope

I'm wondering how to properly sort table data when the data is spread accross multiple tables. I have some app data that is displayed in tables based on the country the app belongs to, i.e., each country has its own table of app data. I'm able to sort the table data by clicking the table headings (app properties), using orderBy, but clicking the heading of one of the country tables sorts all of the country tables. I'm wondering how to isolate the scope so that clicking on the table heading of one country's table of app data only changes the order of it's app data and not the other countries tables of app data. I tried adding the countryId property to the app data and then filtering based on the currently clicked country table but that just causes the other country tables to be empty. What's the proper way to isolate the scope of orderBy?
<div class="table-responsive" ng-repeat="countryReleases in regionRelease.countryReleases">
<h5><strong>{{ countryReleases.countryName }}</strong></h5>
<table id="app" class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th ng-click="vm.sortCountry = countryReleases.countryId; vm.sortName = 'application.name'; vm.sortReverse = !vm.sortReverse">
<span>App Name</span>
<span ng-show="vm.sortName == 'application.name' && !vm.sortReverse" class="pull-right fa fa-caret-up"></span>
<span ng-show="vm.sortName == 'application.name' && vm.sortReverse" class="pull-right fa fa-caret-down"></span>
</th>
<th>App Prop 2</th>
...
</tr>
</thead>
<tbody>
<tr ng-repeat="appReleases in countryReleases.appReleases | filter:vm.sortCountry | orderBy:vm.sortName:vm.sortReverse">
<td>
<img class="thumbnail" ng-src="{{ appReleases.application.icon }}">
...
// Edit:
fixed by passing the scope of the current iteration to orderBy filter in the controller:
<th ng-click="vm.sortName = 'application.name'; vm.sortReverse = !vm.sortReverse; vm.orderByAppCountry(this, vm.sortName, vm.sortReverse)">
...
<tr ng-repeat="appReleases in countryReleases.appReleases">
...
function orderByAppCountry(scope, predicate, reverse) {
scope.countryReleases.appReleases = $filter('orderBy')(scope.countryReleases.appReleases, predicate, reverse);
}
Fixed by adding orderBy filter to controller and calling from click of country table, See edit above.

How do i Selectable continuously table td element onhover cursor pointer in angular Js

My scenario, If i start selecting table td element jan01,feb 01,mar 01 continouly to apri01, apri02,mar 02,feb 02.
It's select table td then change class to "cellselect" and selected td element "datavalselet" val add in one array i.e $scope.selectedCell = [] and
unselect td element value add in $scope.unselectedCell = [].
It's similar like that http://plnkr.co/edit/cCsLf6g83Xhg72mePoFf?p=preview.
But, it's based on cursor pointer in td element its only select. Not hole row and column.
Please see my implement code from http://jsfiddle.net/q4wcgbLq/12/
Also, same functionality work or support to mobile device.
But, I do not want to used jquery and jquery ui selectable function and mouser over and mouser-down event.
How to do this type functionality in anguler js. or is it possible it in angular Js.
i tried using mousedown and mouseup event but its not working properly and not support to mobile device it.
Any other way do this type functionality and also, work on mobile devices using angular Js
How I can achieve this? or please let me know.
I have implement some code below jsfiddle.
In Viewhtml file
<div ng-app>
<div ng-controller="myselectctr">
<table class="cell-box-selection">
<thead>
<tr>
<th ng-repeat="monlist in monthsarr">
{{monlist}}
</th>
</tr>
</thead>
<tr>
<td class="days-val">01</td>
<td ng-repeat="val in valindaysarr " class="mainbox_{{$index}} cellselect" ng-class="{'cellselect': cellbox{{$index}}, 'uncellselect': !cellbox{{$index}}}" ng-click="selectioncell($index)" datavalselet="{{val}}01">{{val}}01</td>
</tr>
<tr>
<td class="days-val">02</td>
<td ng-repeat="val in valindaysarr track by $index" class="mainbox_{{$index*1+7}} smallcell cellselect" ng-class="{'cellselect': cellbox{{$index*1+7}}, 'uncellselect': !cellbox{{$index*1+7}}}" ng-click="selectioncell($index*1+7)" datavalselet="{{val}}02">{{val}}02</td>
</tr>
<tr>
<td class="days-val">03</td>
<td ng-repeat="val in valindaysarr track by $index" class="mainbox_{{$index*1+14}} smallcell cellselect" ng-class="{'cellselect': cellbox{{$index*1+14}}, 'uncellselect': !cellbox{{$index*1+14}}}" ng-click="selectioncell($index*1+14)" datavalselet="{{val}}03">{{val}}03</td>
</tr>
</table>
</div>
</div>
In Controller.js
function myselectctr($scope) {
$scope.selectedCell = [];
$scope.unselectedCell = [];
$scope.monthsarr = ['M/D','Jan','Feb','Mar','Apri', 'May', 'Jun', 'Jul'];
$scope.dayscountarr = ['01','02','03','04', '05','06','07'];
$scope.valindaysarr = ['jan','feb','mar','apri', 'may','jun','jul'];
for(var i=0; i<49; i++){
$scope.selectioncell = function(i){
$scope['cellbox'+i] = !$scope['cellbox'+i];
}
}
}
Can you please any help me?

ng-init miscalculates aliased index after array.splice

I have encountered a strange behavior related to ng-init, any help would be appreciated.
I have a model object which has a flats property that is an array of flat objects. Each flat object has rooms property which is an array of room objects.
I'm trying to display flat and rooms as follows;
<table ng-repeat="flat in model.flats" ng-init="flatIndex = $index">
<thead>
<tr>
<td>{{flatIndex+1}}. {{flat.name}}</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="room in flat.rooms" ng-init="roomIndex = $index">
<td>{{roomIndex+1}}. {{room.name}}</td>
</tr>
</tbody>
</table>
If i delete a flat or room by using array.splice flatIndex and roomIndex variables doesn't seem to update properly even though $index and ui updates properly.
You can see the problem here in action.
Try to delete 1st, 2nd or 3rd flat or room object by clicking the delete link. Deleting last object from the array doesn't really expose the problem.
Any workarounds would also be appreciated.
This is a known behavior when you use ng-init, the scope property values set by ng-init are not watched and they don't update when you remove items from array to reflect the refreshed index position. So don't use ng-init, instead just use $index (deleteFlat($index)) and flat object reference (to get hold of rooms deleteRoom(flat,$index)).
<table ng-repeat="flat in model.flats track by flat.id">
<thead>
<tr>
<td colspan="2">{{$index+1}}. {{flat.name}}</td>
<td>DELETE FLAT</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="room in flat.rooms track by room.id">
<td> </td>
<td>{{$index+1}}. {{room.name}}</td>
<td>DELETE ROOM</td>
</tr>
</tbody>
</table>
and
$scope.deleteFlat = function(flatIndex){
$scope.model.flats.splice(flatIndex,1);
};
$scope.deleteRoom = function(flat,roomIndex){
flat.rooms.splice(roomIndex,1);
};
Plnkr
Or better off use the ids itself, deleteFlat(flat.id) and deleteRoom(room.id, flat).
<table ng-repeat="flat in model.flats track by flat.id">
<thead>
<tr>
<td colspan="2">{{$index + 1}}. {{flat.name}}</td>
<td>DELETE FLAT</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="room in flat.rooms track by room.id">
<td> </td>
<td>{{$index+1}}. {{room.name}}</td>
<td>DELETE ROOM</td>
</tr>
</tbody>
</table>
and
$scope.deleteFlat = function(flatId){
$scope.model.flats.splice(_getItemIndex(flatId, $scope.model.flats), 1);
};
$scope.deleteRoom = function(roomId, flat){
flat.rooms.splice(_getItemIndex(roomId, flat.rooms), 1);
};
function _getItemIndex(imtId, itms){
var id ;
itms.some(function(itm, idx){
return (itm.id === imtId) && (id = idx)
});
return id;
}
Plnkr2

Resources