Angular. Ui-router and access rights to the template

Connected the Ui-router. Displays three different templates in different locations. We send a certain parameter (aka stateParams) to the server, which returns true or false. How do I add this check and where to go, so that the result from the server displays the necessary templates or outputs a template with information about the unavailability of the template? If false all three templates should be unavailable. I tried to solve it head-on by writing a check in templateUrl, it doesn't work and duplicate it for 3 templates clearly not correct.

.config(['$locationProvider','$stateProvider', function($locationProvider,$stateProvider,$http){
        $stateProvider
            .state('page', {
                url: "/page:page",
                views: {
                    "viewVideo": {
                        templateUrl: function (stateParams){
                            $http({
                                url: basePath + '/lesson/GetPageData',
                                method: "POST",
                                data: $.param({order: stateParams.page}),
                            })
                                .success(function (response) {
                                    if(response) return '/index_'+ stateParams.page+'_video.html'
                                })
                        },
                        controller: 'lessonPageCtrl'
                    },
                    "viewText": {
                        templateUrl: function (stateParams){
                           $http({
                                url: basePath + '/lesson/GetPageData',
                                method: "POST",
                                data: $.param({order: stateParams.page}),
                            })
                                .success(function (response) {
                                    if(response) return '/index_'+ stateParams.page+'_text.html'
                                })
                        },
                        controller: 'lessonPageCtrl'
                    },
                    "viewQuiz": {
                        templateUrl: function (stateParams){
                            $http({
                                url: basePath + '/lesson/GetPageData',
                                method: "POST",
                                data: $.param({order: stateParams.page}),
                            })
                                .success(function (response) {
                                    if(response) return '/index_'+ stateParams.page+'_quiz.html'
                                })
                        },
                        controller: 'lessonPageCtrl'
                    }
                }
            })
}]);

I wanted to use solutions to the problem in this way

angular
    .module('lessonApp')
    .run([
        '$rootScope', '$state', '$stateParams',
        function ($rootScope, $state, $stateParams) {

            $rootScope.$state = $state;
            $rootScope.$stateParams = $stateParams;

            $rootScope.$on('$stateChangeStart',
                function (event, toState, toParams, fromState, fromParams) {
                    if (true) {
                        event.preventDefault();
                    }
                }
            );
        }
    ]);

But I have no idea how to push an ajax request through $http into if. Who will show a simple example with Resolve for my problem? Before loading the template, you need to check what the $http ajax request returns

Http://plnkr.co/edit/oILOiXh8iGxoxzT1Xe2j?p=preview

Another question arose. To reduce the load on the server, the data will be extracted from the model PageData, which will be initialized when the page is first loaded:

angular
    .module('lessonApp')
    .run([
    '$rootScope', '$state', '$stateParams','$http',
    function ($rootScope, $state, $stateParams, $http) {

        $http({
            url: basePath + '/lesson/GetPageData',
            method: "POST",
            data: $.param({lecture: idLecture}),
            headers: {'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8;'}
        })
            .success(function (response) {
                $rootScope.pageData = response;
            })

Then, so as not to contact the server when changing the link every time(except in cases when the model will change) I would like to check some value from this model. If for example $rootScope.pageData[0].isDone==true we load the template

 templateUrl: function (stateParams){
                        if ($rootScope.pageData[0].isDone==true)
                        return '/video.html'
                    },

Is this also solved via resolve, or is there something more elementary? And then $rootScope can't be used in $stateProvider

Author: Игорь Баранюк, 2015-12-01

1 answers

You can use the resolve property.

This property is an object containing key-value pairs.:

Key - {string}: name of the dependency to be implemented in the controller.
value - {string|function}:

  • if the string is an alias for the service.
  • if a function - the function value will be embedded. If the function returns Promise, it will be resolved before the controller is created, and the value will be embedded in the controller. If the returned Promise changes to the status rejected, the event $stateChangeError

By subscribing to this event and checking the error, you can perform the necessary processing actions.

For your case: $http the service returns Promise, so it can be moved to the resolve

.state('page', {
    url: "/page:page",
    resolve: {
        auth: function($q, $http){
            return $http({
                        url: basePath + '/lesson/GetPageData',
                        method: "POST",
                        data: $.param({order: stateParams.page}),
                    })
                    .success(function (response) {
                        if(response) return "authorized";
                        
                        return $q.reject('not authorized');
                    });
       }
   },
   ....

Now, in the case when the query returns true everything will appear and if you write in controller

function lessonPageCtrl(auth, .../*другие внедрения $scope и т.д.*/) {
    console.log(auth); //authorized

If the request returns false, we transfer the result to the state rejected and catch it in the handler $stateChangeError

$rootScope.$on('$stateChangeError',
    function(event, toState, toParams, fromState, fromParams, error) {
        console.log(error); // not authorized
    }
);

Usage example

Example with $http, in data.json - value.

Remark
You assign the same controller to three different view, in this case, three controller objects will be created, which they will be unrelated.

 2
Author: Grundy, 2020-06-12 12:52:24