Looking in the source for ngInclude, there seems to be no hook or way to detect directly a 404 (or other) error when the template doesn't exist. You might want to consider a feature request to add this, as it sounds like a useful feature.
However, right now you could do something with a http response interceptor. If there is some way to tell if a http reguest is for a template, say it is in the 'content' directory, you can intercept errors, and do something with them. For example you could replace the data with a custom directive, that then emits an event so controller(s) could respond to it.
The interceptor could be written like:
app.config(function ($httpProvider) {
$httpProvider.interceptors.push('templateInterceptor');
});
// register the interceptor as a service
app.factory('templateInterceptor', function($q) {
return {
'responseError': function(rejection) {
var isTemplate = !!rejection.config.url.match(/^content/g);
if (isTemplate) {
rejection.data = '<div><template-error url="''+ (rejection.config.url) + ''"><strong>Error from interceptor.</strong></template-error></div>';
return rejection;
} else {
return $q.reject(rejection);
}
}
}
});
So when there is an error after fetching something from the 'content' directive, it adds an element <template-error>
in place of the template content. When this is compiled and then linked, it $emit
s a custom event, templateError
, which parent controllers can respond to, by $scope.$on
. So the directive can be code up like:
app.directive('templateError', function() {
return {
restrict: 'E',
scope: {
'url': '='
},
link: function(scope) {
scope.$emit('templateError', {url:scope.url});
}
};
});
And then in the parent controller of the original ngInclude
, you can react to this event:
$scope.$on('templateError', function(e, data) {
$scope.templateError = true;
$scope.templateErrorUrl = data.url;
})
You can see the full working code in this Plunker. Although I think this is slightly hacky, if the Angular team decide to add an $emit
ed event to the code of ngInclude
on error, then it should be easy to just remove the interceptor / your custom element.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…