Smart Tables Pagination Wont Work With Server Side Filtering - angularjs

I have a smart table that I am working on in AngularJS. The table uses a custom pipe in order to search and sort its data. I also require that the table has working pagination, along with a drop down box so you can select the number of rows to be displayed (think datatables).
For searching and sorting, the custom pipe fires off my ajax requests without a problem. However, when I click on any of the page numbers or change the number of rows to show, the pipe is NOT fired.
The page numbers seem to be set to call setPage(page) (this is set by the st-pagination directive) but nothing happens - and no errors are thrown.
How do I get the custom pipe to fire upon changes to the number of rows displayed or when a page # is clicked in the pagination controls?
Here is my HTML:
<table class="table table-striped table-bordered" st-table="leadsCollection" st-safe-src="leads" st-pipe="serverFilter">
...
<tbody>
<tr data-toggle="modal" data-target="#modal-source" ng-repeat="source in leadsCollection" ng-click="rowClick($index);">
<td>{{source.leaddate}}</td>
<td>{{(source.distance > 100) ? 'Long Distance' : 'Local'}}</td>
<td>{{source.origin_city}}, {{source.origin_state}}</td>
<td>{{source.destination_city}}, {{source.destination_state}}</td>
<td>{{source.est_move_date}}</td>
<td>{{source.distance}} mi</td>
<td>{{source.number_bedrooms}} br</td>
<td></td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="8">
<div class="form-group col-md-1">
<label>Show:</label> <select class="form-control" ng-model="itemsByPage"><option value="10">10</option><option value="25">25</option><option value="50">50</option><option value="100">100</option></select>
</div>
<div class="pull-right" st-pagination="" st-items-by-page="itemsByPage"></div>
</td>
</tr>
</tfoot>
</table>
And here is the controller:
.controller('Leads', function ($scope, $http) {
$scope.leads = [];
$scope.leadsCollection = [].concat($scope.leads);
$scope.itemsByPage = "10";
$scope.rowClick = function (idx)
{
$scope.editor = $scope.leads[idx];
}
$scope.serverFilter = function(tablestate)
{
$http.post("/portal/api/loadleads",tablestate).success(function(response){
console.log(response);
$scope.leads = response;
$scope.leadsCollection = [].concat($scope.leads);
});
}
})

In order to get smart tables to fire the filters off, you have to set the numberofpages on data load. To get the above filter to work simply add:
tablestate.pagination.numberOfPages = response.totalPages;
Smart Tables seems to require this to be set in order for it to properly bind the events.

Related

Getting undefined when using target '_blank' with ui-router

Hi I'm having the below issue.
Below is my html page
<div class="content" ng-controller="DataController">
<table class="table table-striped" id="show" ng-if="datalist.length>0">
<thead>
<th>State</th>
<th>District</th>
<th>Non-DND's</th>
</thead>
<tbody>
<tr dir-paginate="data in datalist| filter:search|orderBy:sortKey:reverse|itemsPerPage:10" style="cursor:pointer;">
<td>{{data.state}}</td>
<td>{{data.district}}</td>
<td><a ng-click="getnre(data.nondnd,data.dnd,data.land,data.email)" ui-sref="numsemailsdata" target="_blank">{{data.nondnd.length}}</a></td>
</tr>
</tbody>
</table>
<dir-pagination-controls max-size="10" direction-links="true" boundary-links="true" style="float:right" ng-if="datalist.length>0">
</dir-pagination-controls>
</div>
Below is the code in my controller.js
app.controller("DataController", function($scope, DataService) {
$scope.datalist=DataService.getData();
$scope.getnre=function(ndnd,dnd,land,email) {
$scope.numsem = {
ndnds : ndnd,
dnds : dnd,
lands : land,
emails : email
}
}
});
Below is the numsdetails.html
<div class="content" ng-controller="DataController">
<table class="table table-striped">
<thead>
<th>Non-DND's</th>
</thead>
<tbody>
<tr ng-repeat="ndnd in numsems.ndnds">
<td>{{ndnd}}</td>
</tr>
</tbody>
</table>
</div>
Here I'm displaying the non-dnd's count in my first html page and I need to display the non-dnd's in new tab which is numsemails.html
When I'm trying to bind the data to numsemails.html, I'm getting the data as undefined even I'm binding the data from same controller.
Please help me with a solution.
The reason you are getting undefined for numsems is because when you open a new page (blank) you create an entire new instance of your app. It is like loading the page for the first time. Think of it as a totally different browser instance, because that is what it is. You can pass a parameter using stateparams, this gets passed in the url, however you are trying to pass an entire object so it becomes a bit more difficult.
There are multiple solutions to your problem. You can pass some data in the url, or you can use localstorage, $window, or cookies to store the data. I'm sure there are also other solutions. Choose one of these methods to hand your data properly and we can help you with it.
This issue has been discussed in other threads.
ui-router: open state in new tab with target=“_blank” with object params
Your controller code is wrong, you're missing brackets and braces:
app.controller("DataController", function($scope) {
$scope.datalist = DataService.getData();
$scope.getnre = function(ndnd,dnd,land,email) {
$scope.numsem = {
ndnds : ndnd,
dnds : dnd,
lands : land,
emails : email
};
}
});

Hide table rows in angular Js

I have a table, I am already given it CSS using ng-class if they satisfy a condition. Now I want to show only those rows who satisfy the same condition on a button click. I have wrote a controller which checks if the data received is within 24 hours are not and marks the data cell. Until this it's working.Now I need to add a button and show only the row which has this td marked as not received in time.
<tbody>
<tr ng-repeat ="data in log">
<td>{{data.UniqueId}}</td>
<td>{{data.Name}}</td>
<td ng-class ="{'data-notreceived' : dataNotReceived('data.receivedTime')}">{{data.receivedTime
}}
</tbody>
</table>
I think something like this should work. Basically, clicking the button will toggle between showing all or only the items marked as 'data not received'.
<tbody>
<tr ng-repeat ="data in log" ng-show="showAll || dataNotReceived(data.receivedTime)">
<td>{{data.UniqueId}}</td>
<td>{{data.Name}}</td>
<td ng-class ="{'data-notreceived' : dataNotReceived('data.receivedTime')}">{{data.receivedTime}}
</tr>
</tbody>
// in controller
$scope.showAll = true;
$scope.onButtonClick = function() {
$scope.showAll = !$scope.showAll;
return false;
}
From the information provided in question what I can say is: Use ng-show to show rows based on your condition.
<tr ng-show ="your_condition">
You could also use an ng-if rather than ng-show. See the differences here.
Really depends on how often the hide/show toggle needs to happen.
<tbody>
<tr ng-repeat="data in log" ng-if="showLast24Hrs(data.ReceivedTime)">
<td>{{data.UniqueId}}</td>
<td>{{data.Name}}</td>
<td>{{data.ReceivedTime}}</td>
</tbody>
and then in the controller,
$scope.showLast24Hrs = function(receivedTime){
if($scope.isLast24Hours) {
return receivedTime < 200; // Write your less than 24 hours check here
}
return true;
}
I wrote this demo on Codepen. Hope that helps.

Angular ng-repeat stay paged after filter

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>

displaying selected list of values from one list into another onclick in angularjs

i have list of data displayed in table. As i click any td i display the list of selected values in another table.The Problem is if i select more than one row then in addition to the previous record next selected value should also be displayed but as per my code that do not happen.Should i use checklist? Or changes can be done in the existing one.code is as follows:
<table class="table table-hover" style="width:300px;">
<tr ng-repeat="work in jointworkdata">
<td ng-click="selectedVal(tab,work.jointwork_name)">{{work.jointwork_name}}</td>
</tr>
and display table is:
<table class="table table-hover"><tr>
<td >{{selectedData}}</td></tr>
code in controller is:
$scope.selectedVal = function(tab,val) {
if(tab==1)
{
$scope.selectedData=val;}
};
The output gives one record at a time and not all selected since fucntion is getting called on click.
You can accomplish this with 2 way binding https://docs.angularjs.org/guide/databinding .
Lets say you have a simple Controller that has the primary data to display and then a variable that collected the ones the user is adding on.
app.controller = function($scope) {
$scope.data = [1,2,3,4];
$scope.data2 = new Array();
$scope.add = function(item) {
$scope.data2.push(item);
};
};
Now in the view its simple as displaying both of them
<tr ng-repeat="item in data">
<td ng-click="add(item)">{{ item }}</td>
</tr>
...
<tr ng-repeat="item2 in data2">
<td>{{ item2 }}</td>
</tr>
Two way binding will take care of automatically rerunning that ng-repeat if any new items are added to the data2 array.

turn off re-sorting in angularJS while editing

I have an AngularJS app that lists a bunch of items in a table. Like this:
<table class='unstyled tmain'>
<tr>
<td ng-click='setSort($event)'>X</td>
<td ng-click='setSort($event)'>Desc</td>
<td ng-click='setSort($event)'>created</td>
<td> </td>
</tr>
<tr ng-repeat="item in items | orderBy:itemNormalizationFunction:sortReverse">
<td><input type='checkbox' ng-model='item.done'
ng-click='onCheckedChanged(item)'/></td>
<td><div edit-in-place="item.text"
on-save="updateItemText(value,previousValue,item)"></div></td>
<td><span class='foo'>{{item.created | dateFormatter}}</span></td>
</tr>
</table>
The table headers are clickable to set the sort order. The cell in the 2nd column in each data row is editable "in place" - if you click on the text it gets replaced with an input textbox, and the user can edit the text. I have a little directive enabling that. This all works.
The problem comes in while editing. Suppose I have it set to sort by "description" (the 2nd column). Then if I edit the description (via the edit-in-place directive), as I am typing in the input box, the sort order changes. If I change the first few characters, then angular re-sorts and the item is no longer under my cursor. Nor is it even focused. I have to go hunting through the list to find out where it got re-sorted to, then I can re-focus, and resume typing.
This is kinda lame.
What I'd like to do is tell angular to (a) stop re-sorting while I am keying in the input box, or (b) sort on a separate (not-displayed) index value that preserves the ordering before the edit began. But I don't know how to do either of those. Can anyone give me a hint?
I know this is sort of complicated so I'll try to put together a plunkr to show what's happening.
This is the plunkr that shows how I solved the problem.
http://embed.plnkr.co/eBbjOqNly2QFKkmz9EIh/preview
You can create custom filter and call that only when necessary. Example when you click on 'Grid header' for sorting or after dynamically adding/removing values to array, or simply click of a button(Refresh Grid)
You need to dependency Inject Angular filter and sort filter
angular
.module('MyModule')
.controller('MyController', ['filterFilter', '$filter', MyContFunc])
function ExpenseSubmitter(funcAngularFilter, funcAngularFilterOrderBy) {
oCont = this;
oCont.ArrayOfData = [{
name: 'RackBar',
age: 24
}, {
name: 'BamaO',
age: 48
}];
oCont.sortOnColumn = 'age';
oCont.orderBy = false;
var SearchObj = {
name: 'Bama'
};
oCont.RefreshGrid = function() {
oCont.ArrayOfData = funcAngularFilter(oCont.ArrayOfData, SearchObj);
oCont.ArrayOfData = funcAngularFilterOrderBy('orderBy')(oCont.ArrayOfData, oCont.sortOnColumn, oCont.orderBy);
}
}
and call in HTML something like:
<table>
<thead>
<tr>
<th ng-click="oCont.sortOnColumn = 'age'; oCont.RefreshGrid()">Age</th>
<th ng-click="oCont.sortOnColumn = 'name'; oCont.RefreshGrid()">Name</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="val in oCont.ArrayOfData">
<td>{{val.age}}</td>
<td>{{val.name}}</td>
</tr>
</tbody>
</table>

Resources