Angular ui-router with spa using sticky states not preserving scroll position on first back button

408 Views Asked by At

I'm creating an Angular mobile SPA app and part of the requirements have a substantial amount of list >> details pages. After they filter to populate the list, they can click on the item to go to a details page for it (with crud options if allowed, which rules out just using a modal). I'm saving the relevant data and things in a service, but this does not help maintain the scroll position and ui-router-extras sticky state seems like it would be ideal. I'm using requirejs as well, in case that's relevant. Also, I am using a Kendo ListView bound with a kendo.dataSource if that is relevant.

I've implemented it, but I'm not sure I've done it correctly. I scroll down and click on a list item and it goes to the details. When I click the back button (a directive that uses $window.history.back();, although I tried using $state.go and it did the same thing), it will go back and used the "cached" version, but will be at the top of the list. If I scroll down and click on another item and then go back, it will maintain the scroll position like I expect.

I turned on $stickyStateProvider.enableDebug(true); and the output looks identical from the first to the subsequent calls.

Here's my states config:

return app.config(function ($stateProvider, $stickyStateProvider, $urlRouterProvider) {
    $stickyStateProvider.enableDebug(true);
    $urlRouterProvider.otherwise(function ($injector, $location) {
        var $state = $injector.get("$state");
        $state.go("home");
    });
    $stateProvider.state('home', {
        url: '/home',
        templateUrl: 'app/views/home.html',
        controller: 'homeController',
        controllerAs: "vm"
    })
    .state('cmmenu', {
        url: '/cmmenu',
        templateUrl: 'app/views/cmmenu.html',
        controller: 'cmmenuController',
        controllerAs: "vm"
    })
    .state('areainquiry', {
        //sticky: true,
        abstract: true,
        url: '/areainquiry',
        templateUrl: 'app/views/areainquiry.html'
    })
    .state('areainquiry.list', {
        url: '/areainquirylist',
        views: {
            'areainquirylist@areainquiry': {
                templateUrl: 'app/views/areainquirylist.html',
                controller: 'areainquirylistController',
                controllerAs: "vm"
            }
        },
        sticky: true,
        deepStateRedirect: true
    })
    .state('areainquiry.details', {
        url: '/areainquirydetails/:areaInquiryId',
        views: {
            'areainquirydetails@areainquiry': {
                templateUrl: 'app/views/areainquirydetails.html',
                controller: 'areainquirydetailsController',
                controllerAs: "vm"
            }
        }
    })
    .state('login', {
        url: '/login',
        templateUrl: 'app/views/login.html',
        controller: 'loginController',
        controllerAs: "vm"
    });
})

Here is the areainquiry.html that is the abstract parent view:

<div ui-view="areainquirylist"  ng-show="$state.includes('areainquiry.list')"></div>
<div ui-view="areainquirydetails" ng-show="$state.includes('areainquiry.details')"></div>

Here is the code that is opening this screen. I do not have a named view in my index.html and all views up to areainquiry.html are using the root un-named view (I gave it a name "body" and changed all of them to use it, but it worked the same):

<div class="col-xs-6 col-md-4">
    <a class="btn btn-default fullwidth" ui-sref="areainquiry.list">
        <span class="{{ vm.areaInquiryButtonIcon }}"></span>
        <br />
        {{ vm.areaInquiryButtonText }}
    </a>
</div>

I was trying to figure out a way to do it without the abstract state and just through a parent areainquiry and child areainquiry.detail, but couldn't get it working that way, so went this route.

1

There are 1 best solutions below

0
On

Never mind. It is working. I'm not sure how I fixed it. I was working through another issue (had to do with a factory service), so I'm assuming that fixed it.