2014-12-05 1 views
9

У меня есть основное состояние, доступное по адресу URL http://myapp/validate.Угловой UI-маршрутизатор, доступ к родительскому состоянию и динамическое перенаправление пользователя в определенное дочернее состояние

По достижении этого URL-адреса внутри контроллера я выполняю проверку прав и перенаправляю пользователя в одно из двух дочерних состояний.

Это работает, 80% удовлетворены, но использует некоторые ресурсы и вызывает небольшое мерцание в моем приложении, так как в основном я загружаю представление, которое я НЕ ИСПОЛЬЗУЮ.

Есть ли лучший способ достичь этого?

Любые идеи?

angular.module('app.validate').config(['$stateProvider', function($stateProvider) { 
    $stateProvider 
     .state('validate', { 
      url: '/validate', 
      template: '<ui-view/>', 
      controller: ['$state', 'HasPermission', function ($state, HasPermission) { 

       // Here is where I do my logic. 

       if (HasPermission.get('can-lock-as-admin')) { 
        $state.go('validate.lock-as-admin'); 
       } 

       if (HasPermission.get('can-lock-as-clerk')) { 
        $state.go('validate.lock-as-clerk'); 
       } 
      }] 
     }) 
     .state('validate.lock-as-admin', { 
      templateUrl: 'theUrl', 
      controller: 'ValidateLockAdminCtrl' 
     }) 
     .state('validate.lock-as-clerk', { 
      templateUrl: 'theUrl', 
      controller: 'ValidateLockClerkCtrl' 
     }) 
     .state('validate.commit', { 
      templateUrl: 'theUrl', 
      controller: 'ValidateCommitCtrl' 
     }); 
}]); 
+0

Я думаю, вам нужно избавиться от: 'template: '',' поскольку рендеринг этого пустого представления может вызвать мерцание. –

+0

Позвольте мне проверить, я не уверен, но если нет никаких «», то детские состояния не будут работать. –

+0

Да. дочерние состояния нуждаются в на родительском –

ответ

7

Мерцание связано с тем, что вы на самом деле выпускающего пользователю доступ http://myapp/validate перед перемещением его на правильный путь.
Вы можете избежать этого, перенаправив его на правильный путь, не указав родительский маршрут.

app.run(function($rootScope){ 

    $rootScope.$on('$stateChangeStart', 
    function(e, toState, toParams, fromState, fromParams), { 
     if(toState.name === 'validate') { // some conditional 
     e.preventDefault(); // This tells the app not to move to the validate route 

     if (HasPermission.get('can-lock-as-admin')) { 
      $state.go('validate.lock-as-admin'); 
     } 
     if (HasPermission.get('can-lock-as-clerk')) { 
      $state.go('validate.lock-as-clerk'); 
     } 
     } 
    }); 
    }); 

}); 

Чтобы иметь еще более чистый раствор можно, вероятно, использовать resolve блок, проверить разрешение, но я не на 100% об этом, и у меня нет времени, чтобы проверить это сейчас.
Я бы посоветовал вам взглянуть на this article, так как он объясняет в хорошем смысле похожие сценарии.

0

Если вы не хотите расширить ui-router, я бы посоветовал следующее:

  • Не создавать переходные состояния.

    Двигатель ui-router работает в предположении, что, когда вы направляетесь в состояние и переход успешно, необходимо просмотреть состояние. Поэтому, если вы направляете в состояние и разрешаете его разрешать, фактически пытаясь перейти в другое место, будьте готовы к мерцанию.

    Это приводит к вопросу «Что, если я не позволю государству разрешить и вместо этого перенаправить?». К сожалению, есть некоторые проблемы с перенаправлением, находясь в середине разрешения штата. См. Часть ответа после перерыва.

  • Либо создать резервные объявления ...

    Вместо того, чтобы иметь отдельное переходное состояние, вы можете решить, какие из суб-состояний по умолчанию и прямой на этот вопрос. Там вы можете выполнить свои проверки и, возможно, перенаправить куда-то еще. Это приведет к появлению мерцания в случае перенаправления. Но если ваш по умолчанию хорошо выбран, а перенаправление происходит только иногда, это хорошее начало.

  • ... или непосредственно для исправления пунктов назначения.

    Использование правильной машины должным образом означает направление в состояния, в которых вы действительно хотите, чтобы пользователь пошел. Это означает, что любые проверки должны выполняться до, запускающих переходы состояний. Конечно, это возможно только при программном программировании.Вы по-прежнему нуждаетесь в предыдущей стратегии «резервного копирования», чтобы иметь дело с попыткой пользователя начать в определенном состоянии, введя его URL-адрес.


В качестве альтернативы, вы можете продлить ui-router немного, чтобы разрешить переходы между состояниями во время государственного разрешения. (В прошлый раз, когда я проверил, вы не могли безопасно перенаправить на другое состояние с resolve.) Например, вы можете украсить $state и прекратить попытки перенаправления, пока разрешение состояния уже выполняется (вы можете сказать, наблюдая соответствующие события), а затем перенаправлять на последнее пойманное состояние после завершения разрешения состояния. Если вы сделаете это, вы можете создать переходные состояния, как это:

.state('someTransitionalState', { 
    resolve: { 
     redirect: ['permissions', '$state', '$q', function (permissions, $state, $q) { 
      $state.go(permissions.has(...) ? ... : ...); 
      return $q.reject('transitional state - redirected elsewhere'); 
     }] 
    } 
}) 

Таким образом, переходное состояние никогда не будет решать и все попытки достичь это приведет к достижению других выбранных направлений.

0

Вы можете использовать некоторые пользовательские атрибуты разрешения на маршрутах, которые вы можете проверить, как:

.state('validate.lock-as-admin', { 
      template: '<h1>lock as admin</h1>', 
      permission: 'admin', 
      otherwise: 'validate.lock-as-clert' 
     }) 
     .state('validate.lock-as-clerk', { 
      template: '<h1>lock as clerk</h1>', 
      permission: 'clerk', 
      otherwise: 'validate.lock-as-admin' 
     }) 

Тогда вы могли наблюдать routechanges и сделать некоторые проверки пользовательских разрешений. Вот пример того, как это можно достичь. example

Смежные вопросы