Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS UI Router $state reload child state only

I am using UI router for tabs of a main menu as well as for links within one of the states (users). The users state has a list of users and when a user is clicked, I want to reload the child state only, but it is reloading both the child state and the parent state (users).

Here's my code:

    app.config(function ($stateProvider, $locationProvider, $urlRouterProvider) {     $urlRouterProvider.otherwise("/");     $locationProvider.html5Mode(true);     $stateProvider         .state('home', {             abstract: true,             template: '<div ui-view=""></div>',             controller: 'HomeController as homeCtrl'         })         .state('users', {             parent: 'home',             url: '/users',             templateUrl: '/User/Index',             controller: 'UserController as userCtrl',         })         .state('users.createUser', {             templateUrl: '/User/CreateUser',             controller: 'CreateUserController as cuCtrl'         })         .state('users.editUser', {             templateUrl: '/User/EditUser',             controller: 'EditUserController as euCtrl',             resolve: {                 userInfo: function (contextInfo, userData) {                     return userData.get(contextInfo.getUserKey());                 }             }         })         .state('users.addWebItemsForUser', {             templateUrl: '/User/AddWebItemsForUser',             controller: 'UserWebItemsController as uwiCtrl'         })         .state('users.addReportsForUser', {             templateUrl: '/User/AddReportsForUser',             controller: 'UserReportsController as urCtrl'         })         .state('users.userGroups', {             templateUrl: '/User/UserGroups',             controller: 'UserGroupController as userGroupCtrl'         })         //.state('users.logInWebApp', {         //    template: '<h3>Logging into web app</h3>',         //    resolve: {         //        user: function() {         //            return {         //                //companyId: contextInfo.getCustomerKey()         //                //userId:         //                //password:         //            }         //        }         //    },         //    controller: function() {         //        // need company code, username and password of user then need to open window with webapp url (will that work?) - do we still want to add this functionality?         //    }         //})         .state('links', {             url: '/links',             templateUrl: '/Link/Index',             controller: 'LinkController as linkCtrl'         })         .state('onlrpts', {             url: '/onlineReports',             templateUrl: '/OnlineReport/Index',             controller: 'OnlineReportController as onlRptCtrl'         })         .state('reports', {             url: '/customerReports',             templateUrl: '/CustomerReport/Index',             controller: 'CustomerReportController as custRptCtrl'         }); }) .config(function($provide) {     $provide.decorator('$state', function($delegate, $stateParams) {         $delegate.forceReload = function() {             return $delegate.go($delegate.$current.name, $stateParams, {                 reload: true,                 inherit: false,                 notify: true             });         };         return $delegate;     }); }); 

This is the function in my parent controller (UserController) that is called when a user is clicked:

            this.userTreeClick = function(e) {         contextInfo.setUserKey(e.Key);         contextInfo.setUserName(e.Value);         userCtrl.userKey = e.Key;         $state.forceReload();     }; 

So say I was in the users.userGroups state, when I click on another user, I want only the users.userGroups state to be reloaded. Is this possible? I have looked for an answer via Google and here at StackOverflow, but I haven't found anything that is exactly like what I am trying to do. When I break to check the $state.$current.name - the name is correct - users.userGroups, but it reloads everything instead of just the child state. Any help is very much appreciated!

like image 374
dfstewart3 Avatar asked Aug 14 '14 19:08

dfstewart3


2 Answers

As documented in API Reference , we can use $state.reload:

$state.reload(state)

A method that force reloads the current state. All resolves are re-resolved, controllers reinstantiated, and events re-fired.

Parameters:

  • state (optional)
    • A state name or a state object, which is the root of the resolves to be re-resolved.

An example:

//will reload 'contact.detail' and 'contact.detail.item' states $state.reload('contact.detail'); 

Similar we can achieve with a $state.go() and its options parameter:

$state.go(to, params, options)

...

  • options (optional)
    • location ...
    • inherit ...
    • relative ...
    • notify ...
    • reload (v0.2.5) - {boolean=false|string|object}, If true will force transition even if no state or params have changed. It will reload the resolves and views of the current state and parent states. If reload is a string (or state object), the state object is fetched (by name, or object reference); and \ the transition reloads the resolves and views for that matched state, and all its children states.

Example from https://github.com/angular-ui/ui-router/issues/1612#issuecomment-77757224 by Chris T:

{ reload: true } // reloads all, { reload: 'foo.bar' } // reloads top.bar, and any children { reload: stateObj } // reloads state found in stateObj, and any children 

An example

$state.go('contact', {...}, {reload: 'contact.detail'}); 
like image 175
Radim Köhler Avatar answered Oct 02 '22 20:10

Radim Köhler


The current ui-router (0.2.14 and above) added support to reload child state.

Simply put $state.go('your_state', params, {reload: 'child.state'}); will do the job.

See: https://github.com/angular-ui/ui-router/issues/1612 and https://github.com/angular-ui/ui-router/pull/1809/files

like image 20
lcltj Avatar answered Oct 02 '22 19:10

lcltj