web-dev-qa-db-fra.com

AngularJS UI Router $ state recharge l'état enfant uniquement

J'utilise le routeur UI pour les onglets d'un menu principal ainsi que pour les liens dans l'un des états (utilisateurs). L'état des utilisateurs a une liste d'utilisateurs et lorsqu'un utilisateur clique dessus, je souhaite recharger uniquement l'état enfant, mais il recharge à la fois l'état enfant et l'état parent (utilisateurs).

Voici mon 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;
    });
});

C'est la fonction de mon contrôleur parent (UserController) qui est appelée lorsqu'un utilisateur clique sur:

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

Supposons donc que j'étais dans l'état users.userGroups, lorsque je clique sur un autre utilisateur, je veux que seul l'état users.userGroups soit rechargé. Est-ce possible? J'ai cherché une réponse via Google et ici à StackOverflow, mais je n'ai rien trouvé qui ressemble exactement à ce que j'essaie de faire. Lorsque je me casse pour vérifier l'état $ $. Current.name - le nom est correct - users.userGroups, mais il recharge tout au lieu de simplement l'état enfant. Toute aide est fortement appréciée!

29
dfstewart3

Comme indiqué dans l'API Reference, nous pouvons utiliser $state.reload:

$ state.reload (état)

Une méthode qui force à recharger l'état actuel. Toutes les résolutions sont résolues à nouveau, les contrôleurs sont rétablis et les événements sont à nouveau déclenchés.

Paramètres:

  • state (facultatif)
    • Un nom d'état ou un objet d'état, qui est la racine des résolutions à résoudre à nouveau.

Un exemple:

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

On peut obtenir la même chose avec un $state.go() et son paramètre options:

$ state.go (to, params, options)

...

  • options (facultatif)
    • location ...
    • inherit ...
    • relative ...
    • notify ...
    • reload (v0.2.5) - {boolean = false | string | object}, si true force la transition même si aucun état ou paramètre n'a changé. Il rechargera les résolutions et les vues de l'état actuel et des états parents. Si recharger est une chaîne (ou un objet d'état), l'objet d'état est récupéré (par nom ou référence d'objet); et\la transition recharge les résolutions et les vues pour cet état correspondant, et tous ses états enfants.

Exemple de https://github.com/angular-ui/ui-router/issues/1612#issuecomment-77757224 par 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

Un exemple

$state.go('contact', {...}, {reload: 'contact.detail'});
30
Radim Köhler

Le routeur ui actuel (0.2.14 et supérieur) a ajouté la prise en charge du rechargement de l'état enfant.

Mettez simplement $state.go('your_state', params, {reload: 'child.state'}); fera l'affaire.

Voir: https://github.com/angular-ui/ui-router/issues/1612 et https://github.com/angular-ui/ui-router/pull/1809/fichiers

28
lcltj

Je l'ai fait fonctionner. J'ai utilisé ce que Radim a suggéré, mais j'ai dû ajouter l'élément rl à l'état.

.state('users.userGroups', {
    url: '/userGroups/{userTrigger}',
    templateUrl: '/User/UserGroups',
    controller: 'UserGroupController as userGroupCtrl'
})

et dans mon contrôleur, lorsqu'un utilisateur clique sur un lien, j'utilise le $state.transitionTo:

var params = angular.copy($state.params);
params.userTrigger = params.userTrigger === null ? "" : null;
$state.transitionTo($state.current, params, { reload: false, inherit: true, notify: true }); 

Juste un info pour tous les autres débutants:

après avoir ajouté le rl au .state, J'ai commencé à avoir des problèmes avec mes appels API. Il ajoutait les URL aux méthodes API avec l'URL dans mon .state. Vous devez juste être sûr d'avoir un leader / dans vos URL api:

.factory('usersInGroup', function($http) {
    return {
        get: function(groupName) {
            return $http.get('/api/UserApi/GetInGroup/' + groupName);
        }
    }

J'ai vu et appris des trucs assez intéressants en essayant de se débrouiller à travers ça ...

1
dfstewart3