Smart-Table
Smart-Table copied to clipboard
Restore the state of a SmartTable - filters and page
AngularJs v 1.6.6; SmartTable v 2.1.8
I have items in row like [id] [name] [edit]
.
When the user edits an item(/items/1/edit
), the item's EditPage contains a "back to list" link (/items
);
That link returns the user to the list of the items. Now the problem is that in that case the page is always the first one, and any applied filters are lost.
Is there a way to say to the SmartTable to remember and restore the "before-edit mode" table state?
Hello @serhioV,
there is an example of the Persist table state in the documentation. Here is the plunk for it
Thank you, MrWook, for the precious suggestion. In my case it really restores the filter, but resets the pagination. because of
angular.extend(tableState, savedState
ctrl.pipe(); /* here the pagination is gone */
I have the following directive that filters the table for min-max update date:
app.directive('stDateRange', [function () {
return {
restrict: 'E',
require: '^stTable',
templateUrl: '/templates/stDateRange.en.html',
scope: false,
link: function (scope, element, attr, ctrl) {
var tableState = ctrl.tableState();
scope.$watchGroup(["minDate", "maxDate"],
function (newValues, oldValues) {
if (newValues) {
var start = newValues[0] || Date.MIN_VALUE;
var end = newValues[1] || Date.MAX_VALUE;
if (start && end) {
var d1 = new Date(start);
var d2 = new Date(end);
ctrl.search({
after: d1.getTime(),
before: d2.getTime()
}, 'modifiedOn');
}
}
}
);
}
};
}
]);
I observed that the pagination is gone when I refresh the page because the saveCopy
the first time collection is loaded in SmartTable table controller is empty.
The filter/search keyword is perserved, but the pagination is gone.
function StTableController($scope, $parse, $filter, $attrs) {
var propertyName = $attrs.stTable;
var displayGetter = $parse(propertyName);
var displaySetter = displayGetter.assign;
var safeGetter;
var orderBy = $filter('orderBy');
var filter = $filter('filter');
var safeCopy = copyRefs(displayGetter($scope)); // empty here, so the pagination reset to '0'
Hello @serhioV,
i don't know what you are doing wrong, but in the example it will also save the pagination. If i should help you more i suggest that you create a plunk with your problem.
Hi @MrWook thanks for your reply.
Here is my plunk
When refreshing
the pagintion is reset to the first page,
and another * problem is that the "data" filter also is not remembered.
Hello @serhioV,
this took me a while to figure out the problem..... Since version 1.2.7 the Persist table state example isn't working anymore because inside the pipe function the pagination start will be set.
For async data it will work when you delete ctrl.pipe();
inside the stPersist directive but this will destroy the Persist table state for sync data.
And last but not least there is a lot of thing that you can improve in your code. The pipe function from smartTable is triggered 6 times in your example and because of that the workaround that i mentioned won't work.
You are mixing Angular coding styles. When you use the "Ctrl AS tc" stop using the $scope inside the controller and only use the object notation within the html.
But the most important thing is try not to use ngInit. It's even written in the angular documentation. The things you want to "init" aren't necessary for it. You can just define it inside the controller.
Hello @MrWook and thanks for trying to help ! )
I use ngInit
because I need to pass some data from the ServerSide code (ASP.NET) to Angular Controller, so I didn't find another way to do it.
I commented in the plunk the ctrl.pipe()
, but this didn't help...
I observed that the problem is that the safeCopy
is empty the first time (after the page reload) it passes to the Controller in my case, and this is why the pagination is reset.
Hello @serhioV,
if you want to refere to the documentation with
injecting data via server side scripting.
This is something like this with PHP:
<div ng-init="data=<?php echo $some_data;?>"></div>
So it is literally injecting some data from php into the HTML inside the ng-init. But if you can use $http requests you don't need ng-init. This can be done in the controller.
Like i said your code triggers the pipe() function 6 times it should only trigger it once. the are reseting the pagination at some point.
actually my ASP.NET code is like this
But even if it triggers it 6 times... is the very first time of "pipe" that the pagination is reset, because when the SmartTable controller is loaded, the safeCopy
appears to be empty, but it should not be...:
Then i didn't said anything sry.
Did you initialized the variables for the table, displayed and tc.table.records ?
yes, but I suppose the controller is loaded first, only then the function go()
is thiggered, and then I asynchronoysly load the records, as in the plunk
with the Promise.resolve(myRecords)
I simulate the $http.get('/records')
Here I load all the all.records
, and then replace the theme
, relevance
etc ids
by respective textual values...
finally, the resulting table.records
serves as source for the SmartTable, but is too late, the controller already reset the safeSoucre and then pipe()
reset the pagination.
I did't meant the controller.
Are those two variables displayed
and tc.table.records
initialized as an array before the data is loaded asynchronoysly ?
in the plunk I provided tc.table.records where not initialized as an empty array. I added this but this didn't fix the problelm.
The displayed was initialized, now the plunk code looks like:
I even changed the $scope usage, you said do not mix, I changed like this
and then changed
app.controller("tablesController", ["$scope", "$http", "$q", function ($scope, $http, $q) {
var tc = this;
tc.all = {};
tc.table = {};
tc.table.records = [];
tc.table.displayed = [];
but all that didn't help to keep the current page to be reloaded correctly. I am on the plunker chat, if needed ;)
Okey but still your table triggeres the pipe function 6 time and that will overwrite the tablestate. If you fix that it should work. Another option would to create your own pipe function and try handle the tablestate on your own.
I can't debug your whole code that is something that you need to do on your own. After all SmartTable is working like it should be.
The solution I came up with. It works for me haha.
I've added var initialLoad
because it seems that smart-table overrides pagination.start
on initial load even when disabling ctrl.pipe();
So i've decided to put the the intial storage state loader into a method called getSavedState
and when smart-table initialises, it will trigger the watch and that's when we call the getSavedState
method to extend ctrl.tableState()
but only if it is the initial load.
.directive('stPersist', function () {
return {
require: '^stTable',
link: function (scope, element, attr, ctrl) {
var nameSpace = attr.stPersist;
var initialLoad = true;
// save the table state every time it changes
scope.$watch(function () {
return ctrl.tableState();
}, function (newValue, oldValue) {
if (newValue !== oldValue) {
if (initialLoad) {
getSavedState();
initialLoad = false;
return;
}
localStorage.setItem(nameSpace, JSON.stringify(newValue));
}
}, true);
function getSavedState() {
// fetch the table state when the directive is loaded
if (localStorage.getItem(nameSpace)) {
var savedState = JSON.parse(localStorage.getItem(nameSpace));
var tableState = ctrl.tableState();
angular.extend(tableState, savedState);
ctrl.pipe();
}
}
}
};
});
For anyone running into this issue, the start page is set to 0 when something is changed, if you do some async loading in your controller, it will always set to 0
I changed
$scope.$watch(function() {
var safeSrc = safeGetter($scope);
return safeSrc ? safeSrc.length : 0;
}, function(newValue, oldValue) {
if (newValue !== safeCopy.length) {
updateSafeCopy();
}
});
$scope.$watch(function() {
return safeGetter($scope);
}, function(newValue, oldValue) {
if (newValue !== oldValue) {
// tableState.pagination.start = 0;
updateSafeCopy();
}
});
It will prevent setting the page to 0 after an async update.