Angularjs, как проверить, существует ли файл шаблона

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

Вот мой код:

    .when("/:page", angularAMD.route({

        templateUrl: function (rp) { 
                     return 'public/templates/' + rp.page.replace('.html', '') + '.php'; },

        resolve: {
        load: ['$q', '$rootScope', '$location', 
            function ($q, $rootScope, $location) {

                 var path = $location.path();
                 //console.log(path);
                 var parsePath = path.split("/");

                 var controllerName = parsePath[1];
                 controllerName = controllerName.replace('.html', '').replace('_', '');
                 var loadController = "public/js/controllers/" +  
                                       controllerName + "Controller.js";

                 var deferred = $q.defer();
                 require([loadController], function () {
                        $rootScope.$apply(function () {
                        deferred.resolve();
                 });
            });
            return deferred.promise;
            }]
        }

    }))

Я хочу, чтобы до этого return 'public/templates/' + rp.page.replace('.html', '') + '.php'; } он должен проверить, существует ли этот файл, в противном случае я хочу перенаправить на страницу 404.

что происходит, когда я посещу какую-то недействительную ссылку, я не получаю статус 404, вместо этого он загружает основной файл index.html, и по этой причине он запускает тот же код в бесконечном цикле, в последнем браузере висит.

Цените свою помощь, спасибо.

Ответ 1

В ngRoute вам нужно настроить маршруты в блоке config, а внутри блока конфигурации вы не сможете использовать фабрики и службы, так что вы можете использовать простой трюк, чтобы проверить, существует ли шаблон, и если не верните страницу 404.

var checkTplUrl = function(url) {
    var http = new XMLHttpRequest();
    http.open('HEAD', url, false);
    http.send();
    return (http.status !== 404) ? url : './404.html';
};


.when("/:page", angularAMD.route({

    templateUrl: function (rp) {
        return checkTplUrl('public/templates/' + rp.page.replace('.html', '') + '.php'); },

    resolve: {
        load: ['$q', '$rootScope', '$location',
            function ($q, $rootScope, $location) {

                var path = $location.path();
                //console.log(path);
                var parsePath = path.split("/");

                var controllerName = parsePath[1];
                controllerName = controllerName.replace('.html', '').replace('_', '');
                var loadController = "public/js/controllers/" +
                        controllerName + "Controller.js";

                var deferred = $q.defer();
                require([loadController], function () {
                    $rootScope.$apply(function () {
                        deferred.resolve();
                    });
                });
                return deferred.promise;
            }]
    }

}))

Рабочий пример: https://plnkr.co/edit/1UjlFgT7dazMZOrAhZzY?p=info

Ответ 2

 (or $scope.$on)
 $rootScope.$on("$routeChangeError", function(event, current, previous, eventObj) {
    //redirect your user to custom 404 page;
  });

Ответ 3

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

Без обработки и регистрации этих событий $routeChange (например, при использовании ui-router $stateChange Events) вы в основном слепы и пропустите ошибки и дублируете изменения маршрута и другие неприятные вещи...

Здесь пример использования ui-router при использовании базовой маршрутизации angular использует события respecitve маршрутизатора angular.

angular.module('yourMainModuleName', ['your dependencies'])

.config(['$someProvider', function(someProvider) {
    // do setup all your global providers here
    // e.g. $http, restangular, ui-router, angular-translate....

}   ])

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

    // put ui-router $state on $rootScope, so we have access to it in all $scopes
    $rootScope.$state = $state;
    $rootScope.$stateParams = $stateParams;

        $rootScope.$on("$stateChangeStart", function (event, toState, toParams, fromState, fromParams) {
            // always see what happens in your app!
            console.debug('stateChangeStart from: ' + (fromState && fromState.name) + ' to: ' + toState.name);
            // handle auth here as well, check whether user is allowed to go to this state, abort if not
            ...
        });

         $rootScope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState, fromParams) {
            // see what happens in your app!
            console.debug('stateChangeSuccess from: ' + (fromState && fromState.name) + ' to: ' + toState.name);
         });

        // log stateChangeErrors
        $rootScope.$on("$stateChangeError", function (event, toState, toParams, fromState, fromParams, error) {
            console.log('Error on StateChange from: "' + (fromState && fromState.name) + '" to:  "'+ toState.name + '", err:' + error.message + ", code: " + error.status);
            $state.go('home');
         });

}]);

Ответ 4

Создайте службу, которая проверяет наличие файла и возвращает обещание!

$http.head("template2check").then(function () {
                return true;
            }, function () {
                return false;
            });

В контроллере используйте службу:

<service>.<service method>.then(function (found) {
     if (found) {......
});