javascript - Making AngularJS ui-router / app wait for $http data to prevent FOUC -
i have following question... or situation. have states defined in angularjs app, so...
$stateprovider .state('myapp', { abstract: true, template: '<ui-view/>' }) .state('myapp.stateone', { url: 'state1', templateurl: '/an/views/state-1.html', controller: 'stateonectrl' }) .state('myapp.statetwo', { url: 'state2', templateurl: '/an/views/state-2.html' controller: 'statetwoctrl' }) .state('myapp.statethree', { url: 'state3', templateurl: '/an/views/state-3.html' controller: 'statethreectrl' })
there more states , have changed naming example, suppose need check if user allowed see / load 'mayapp.statethree'
. can determine asking backend. have service (in example called isallowedservice
) deal requests / provide access , write logic check in .run()
block in app.js file example:
.run(['isallowedservice', '$state', function (isallowedservice, $state) { $rootscope.$on('$statechangesuccess', function (event, tostate, toparams, fromstate) { // check if going sfm.addcontacts , if allowed to... if (tostate.name === 'myapp.statethree') { isallowedservice.checkifisallowed().then(function (resp) { if(resp.allowed === false) { $state.go('myapp.stateone'); } }); } }); }]);
this works doesn't wait until result service 'mayapp.statethree' loaded redirected if necessary. quick flash of page before redirected. put same code 'statethreectrl'
still flash / fouc. possible resolve when defining states, know won't work this...
.state('myapp.statethree', { url: '/an/state3', templateurl: '/an/views/state-3.html' controller: 'statethreectrl', resolve: { isallowed : function () { isallowedservice.checkifisallowed().then(function (resp) { return resp; }) } }
i realise wouldn't able inject service (or $http
service) possible me somehow pause loading of view / controller of 'mayapp.statethree
' until result isallowedservice.checkifisallowed()
. advice on how structure app / code appreciated. have used ng-cloak in html view did nothing!
actually you're doing right in application's run block. except not preventing anything. can achieve adding:
event.preventdefault(); //prevent going page
furthermore, can add custom data $states , allow verify conditions criteria. e.g.:
$stateprovider.state('home', { controller: 'homecontroller home', url: '/home', templateurl: 'home.html', data: { roles: [roles.anonymous] }}); //this can condition $stateprovider.state('user', { controller: 'usercontroller user', url: '/user', templateurl: 'user.html', data: { roles: [roles.admin, roles.user] }});
you can retrieve custom data in $statechangestart event:
$rootscope.$on('$statechangestart', function (event, next) { if (!yourservice.isauthorized(next.data.roles)) { event.preventdefault(); //prevent going page -> no flickering $state.go('403'); //or whatever desired. } });
you see flickering because you're using promise , first page gets redirected when promise furfilled. can stop flickering preventing default action, authorize , continue flow desire when promise resolves.
if (tostate.name === 'myapp.statethree') { event.preventdefault(); //preventing request. isallowedservice.checkifisallowed().then(function (resp) { if(resp.allowed === false) { $state.go('myapp.stateone'); } else { //he allowed go state three. $state.go('myapp.statethree'); } }, function() { //in case server has no answer $state.go('myapp.stateone'); //you want prevent } );
in opinion, if these conditions not change during runtime, i.e. user role based, can retrieve them upon user verification don't need promise begin with. hope helps.
Comments
Post a Comment