From e4419daf705d6d2d116ced573f72c24b5c53be1f Mon Sep 17 00:00:00 2001 From: Caitlin Potter Date: Wed, 15 Jan 2014 16:57:50 -0500 Subject: [PATCH] feat(ngInclude): emit $includeContentError when HTTP request fails This adds a scope event notification when a template fails to load. This can have performance implications, and unfortunately cannot at this moment be terminated with preventDefault(). But it's nice to be notified when problems occur! Closes #5803 --- src/ng/directive/ngInclude.js | 15 ++++++++++++++- test/ng/directive/ngIncludeSpec.js | 23 +++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/ng/directive/ngInclude.js b/src/ng/directive/ngInclude.js index 38a9e005..603fa482 100644 --- a/src/ng/directive/ngInclude.js +++ b/src/ng/directive/ngInclude.js @@ -159,6 +159,16 @@ * @description * Emitted every time the ngInclude content is reloaded. */ + + +/** + * @ngdoc event + * @name ng.directive:ngInclude#$includeContentError + * @eventOf ng.directive:ngInclude + * @eventType emit on the scope ngInclude was declared in + * @description + * Emitted when a template HTTP request yields an erronous response (status < 200 || status > 299) + */ var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$animate', '$sce', function($http, $templateCache, $anchorScroll, $animate, $sce) { return { @@ -227,7 +237,10 @@ var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$animate' currentScope.$emit('$includeContentLoaded'); scope.$eval(onloadExp); }).error(function() { - if (thisChangeId === changeCounter) cleanupLastIncludeContent(); + if (thisChangeId === changeCounter) { + cleanupLastIncludeContent(); + scope.$emit('$includeContentError'); + } }); scope.$emit('$includeContentRequested'); } else { diff --git a/test/ng/directive/ngIncludeSpec.js b/test/ng/directive/ngIncludeSpec.js index 9f38eb92..828c6d20 100644 --- a/test/ng/directive/ngIncludeSpec.js +++ b/test/ng/directive/ngIncludeSpec.js @@ -143,6 +143,29 @@ describe('ngInclude', function() { })); + it('should fire $includeContentError event when content request fails', inject( + function($rootScope, $compile, $httpBackend, $templateCache) { + var contentLoadedSpy = jasmine.createSpy('content loaded'), + contentErrorSpy = jasmine.createSpy('content error'); + + $rootScope.$on('$includeContentLoaded', contentLoadedSpy); + $rootScope.$on('$includeContentError', contentErrorSpy); + + $httpBackend.expect('GET', 'tpl.html').respond(400, 'nope'); + + element = $compile('
')($rootScope); + + $rootScope.$apply(function() { + $rootScope.template = 'tpl.html'; + }); + $httpBackend.flush(); + + expect(contentLoadedSpy).not.toHaveBeenCalled(); + expect(contentErrorSpy).toHaveBeenCalledOnce(); + expect(element.children('div').contents().length).toBe(0); + })); + + it('should evaluate onload expression when a partial is loaded', inject( putIntoCache('myUrl', 'my partial'), function($rootScope, $compile) {