AngularJS 路由,如何检查模板文件是否存在?

11

我在我的应用程序中使用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,因此会开始运行同样的代码进入一个无限循环,最终浏览器崩溃。

感谢您的帮助,谢谢。


请问您能否提供一些关于如何使用 $routeChangeError 的示例? - Indian Dollar
查看这个链接:http://stackoverflow.com/questions/20894568/display-specific-template-on-routechangeerror - micronyks
1
我的问题是,首先在路由更改时我没有收到任何错误提示,但它加载的不是模板文件,而是主索引文件index.html,我无法检测到任何未找到的错误。我有一个解决方案,如何发送ajax请求到该文件,然后使用状态码?你认为这个方法好还是不好? - Indian Dollar
你解决了这个问题吗?实际上,这里还没有任何解决该问题的内容。 - Murray Rowan
@MurraySmith 不,这件事对我来说仍然是个谜团。没有解决方案。 - Indian Dollar
显示剩余5条评论
4个回答

1
在ngRoute中,您需要在config块中配置路由,而且在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


当我在一般路由中带有参数运行此函数时,它总是返回404错误。 - Coded Container

0
创建一个服务,检查文件是否存在并返回一个Promise!
$http.head("template2check").then(function () {
                return true;
            }, function () {
                return false;
            });

在控制器中使用服务:
<service>.<service method>.then(function (found) {
     if (found) {......
});

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

但是我应该把这段代码放在哪里呢?是在load: ['$q', '$rootScope', '$location',部分吗?我已经尝试过了,但不起作用,原因是即使URL无效,我也没有收到错误提示。 - Indian Dollar

0

在任何非平凡的angular.js应用程序中,您应该做一些事情,最好的地方可能就是在定义主模块的位置,然后是配置块和运行块。

如果不处理和记录那些$routeChange事件(或使用ui-router $stateChange事件),您基本上是盲目的,会错过错误、重复路由更改和其他讨厌的事情...

这里是使用ui-router的示例,如果使用angular基本路由,请使用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');
         });

}]);

1
我理解这个问题,但我的问题是我的脚本没有返回错误。举个例子,假设我运行这个URL mydomain.com/hello.html,现在脚本将从此路径public/templates/hello.html返回模板文件,但实际上这个hello.html根本不存在,所以它不会加载此文件或给出错误,而是加载主应用程序文件index.html,我们在其中包含angularjs库,因为包含了index.html,它会循环加载angularjs库,因此产生大量的ajax调用,最后浏览器崩溃。我希望我能够清楚地解释我的情况。 - Indian Dollar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接