Reputation: 301
I am using angularjs in my application, all works well but before loading the template I just want to check that it actually exists on its given path.
Here is my code :
.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;
}]
}
}))
I want that before doing this return 'public/templates/' + rp.page.replace('.html', '') + '.php'; }
it must check if this file exists, otherwise I want to redirect to 404 page.
what now happens is, when I visits some invalid link, I dont get 404 status, instead it loads the main index.html file, and for that reason, it starts running the same code in an infinite loop, at last browser hangs.
Appreciate your help, thanks.
Upvotes: 11
Views: 3868
Reputation: 531
In ngRoute, you need to configure the routes in the config
block, and inside config block you can't use factories and services,
so you can use a simple trick to check if template exists, and if not return your 404 page.
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;
}]
}
}))
Working example: https://plnkr.co/edit/1UjlFgT7dazMZOrAhZzY?p=info
Upvotes: 1
Reputation: 5024
Create a service that check if the file exist and returns a promise!
$http.head("template2check").then(function () {
return true;
}, function () {
return false;
});
In the controller use the service:
<service>.<service method>.then(function (found) {
if (found) {......
});
Upvotes: 0
Reputation: 3141
There are a few things you should just do in any non-trivial angular.js app, probably the best place for them is right where you define your mainmodule, then a config block and then a run block.
Without handling and logging those $routeChange Events (resp. when using ui-router $stateChange Events) you are basically blind and will miss errors and duplicate route changes and other nasty things...
Here the example when using ui-router, if using angular basic routing use the respecitve events of angular router.
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');
});
}]);
Upvotes: 0
Reputation: 55443
(or $scope.$on)
$rootScope.$on("$routeChangeError", function(event, current, previous, eventObj) {
//redirect your user to custom 404 page;
});
Upvotes: 0