Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restore the state of a SmartTable - filters and page #825

Open
moldovans opened this issue Jan 15, 2018 · 17 comments
Open

Restore the state of a SmartTable - filters and page #825

moldovans opened this issue Jan 15, 2018 · 17 comments

Comments

@moldovans
Copy link

moldovans commented Jan 15, 2018

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?

@MrWook
Copy link
Contributor

MrWook commented Jan 16, 2018

Hello @SerhioV,

there is an example of the Persist table state in the documentation. Here is the plunk for it

@moldovans
Copy link
Author

moldovans commented Jan 16, 2018

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');
                        }
                    }

                }
            );
        }
    };
}
]);

@moldovans
Copy link
Author

moldovans commented Jan 18, 2018

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'

@MrWook
Copy link
Contributor

MrWook commented Jan 18, 2018

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.

@moldovans
Copy link
Author

moldovans commented Jan 18, 2018

Hi @MrWook thanks for your reply.

Here is my plunk

When refreshing
image

the pagintion is reset to the first page,

and another * problem is that the "data" filter also is not remembered.

@MrWook
Copy link
Contributor

MrWook commented Jan 19, 2018

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.

@moldovans
Copy link
Author

moldovans commented Jan 19, 2018

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.

@MrWook
Copy link
Contributor

MrWook commented Jan 19, 2018

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.

@moldovans
Copy link
Author

moldovans commented Jan 19, 2018

actually my ASP.NET code is like this
image

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...:

image

@MrWook
Copy link
Contributor

MrWook commented Jan 19, 2018

Then i didn't said anything sry.

Did you initialized the variables for the table, displayed and tc.table.records ?

@moldovans
Copy link
Author

moldovans commented Jan 19, 2018

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
image

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.

@MrWook
Copy link
Contributor

MrWook commented Jan 19, 2018

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 ?

@moldovans
Copy link
Author

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:
image

@moldovans
Copy link
Author

moldovans commented Jan 19, 2018

I even changed the $scope usage, you said do not mix, I changed like this

image

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 ;)

@MrWook
Copy link
Contributor

MrWook commented Jan 23, 2018

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.

@YussufElarif
Copy link

YussufElarif commented Jul 20, 2018

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();
                        }
                    }
                }
            };
        });

@mjumelet
Copy link

mjumelet commented Jun 23, 2019

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants