Looking at the source for ngInclude , it seems that there is no hook or way to detect directly a 404 error (or another) when the pattern does not exist. You might want to consider requesting a function to add this, as it sounds like a useful function.
However, you can now do something with an HTTP interceptor. If there is some way to find out if the http template is suitable for the template, let's say that it is in the "content" directory, you can catch errors and do something with them. For example, you can replace data with a custom directive that then throws an event so that the controller can respond to it.
The interceptor can be written like this:
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); } } } });
Therefore, when an error occurs after receiving something from the 'content' directive, it adds a <template-error> element instead of the template content. When it is compiled and then connected, it has a $emit custom templateError event, which parent controllers can respond to, on $scope.$on . Thus, the directive can be written as follows:
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 respond 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 a bit hacked, if the Angular team decides to add the $emit ed event $emit code on error, then it should be easy for you to simply remove the interceptor / your user element.