Skip to content

Commit

Permalink
feat(lib): add support for showing error message on element load error
Browse files Browse the repository at this point in the history
  • Loading branch information
tomastrajan committed Jul 20, 2019
1 parent 7c328a5 commit 3fa7246
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,25 @@ import { LazyElementDirective } from './lazy-element.directive';
<p class="loading">Loading...</p>
</ng-template>
<some-element
*axLazyElement="'http://elements.com/some-element'; loading: loading"
*axLazyElement="
'http://elements.com/some-element';
loadingTemplate: loading
"
></some-element>
</div>
<div *ngIf="useErrorTemplate">
<ng-template #loading>
<p class="loading">Loading...</p>
</ng-template>
<ng-template #error>
<p class="error">Loading failed...</p>
</ng-template>
<some-element
*axLazyElement="
'http://elements.com/some-element';
loadingTemplate: loading;
errorTemplate: error
"
></some-element>
</div>
<div *ngIf="useModule">
Expand All @@ -37,6 +55,7 @@ class TestHostComponent {
addSameElement = false;
addOtherElement = false;
useLoadingTemplate = false;
useErrorTemplate = false;
useModule = false;
}

Expand Down Expand Up @@ -120,6 +139,35 @@ describe('LazyElementDirective', () => {
});
});

it('renders error template loading of element failed', done => {
const consoleErrorSpy: jasmine.Spy = spyOn(console, 'error').and.stub();
expect(document.querySelector('.loading')).toBe(null);
expect(document.querySelector('.error')).toBe(null);

testHostComponent.useErrorTemplate = true;
fixture.detectChanges();

expect(document.querySelector('.loading').textContent).toBe('Loading...');
expect(document.querySelector('.error')).toBe(null);

appendChildSpy.calls.argsFor(0)[0].onerror('404');

fixture.detectChanges();

setTimeout(() => {
expect(consoleErrorSpy).toHaveBeenCalledTimes(1);
expect(consoleErrorSpy).toHaveBeenCalledWith(
'@angular-extensions/elements - Loading of element <some-element> failed, please provide <ng-template #error>Loading failed...</ng-template> and reference it in *axLazyElement="errorTemplate: error" to display customized error message in place of element'
);
expect(document.querySelector('.loading')).toBe(null);
expect(document.querySelector('.error').textContent).toBe(
'Loading failed...'
);
consoleErrorSpy.and.callThrough();
done();
});
});

it('uses type module on script tag when specified', () => {
fixture.detectChanges();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@ import {

import { LazyElementsLoaderService } from '../lazy-elements-loader.service';

const LOG_PREFIX = '@angular-extensions/elements';

@Directive({
selector: '[axLazyElement]'
})
export class LazyElementDirective implements OnInit {
@Input('axLazyElement') url: string;
@Input('axLazyElementLoading') loadingTemplateRef: TemplateRef<any>; // tslint:disable-line:no-input-rename
@Input('axLazyElementLoadingTemplate') loadingTemplateRef: TemplateRef<any>; // tslint:disable-line:no-input-rename
@Input('axLazyElementErrorTemplate') errorTemplateRef: TemplateRef<any>; // tslint:disable-line:no-input-rename
@Input('axLazyElementModule') isModule: boolean; // tslint:disable-line:no-input-rename

constructor(
Expand All @@ -35,6 +38,16 @@ export class LazyElementDirective implements OnInit {
.then(() => {
this.vcr.clear();
this.vcr.createEmbeddedView(this.template);
})
.catch(() => {
this.vcr.clear();
if (this.errorTemplateRef) {
this.vcr.createEmbeddedView(this.errorTemplateRef);
} else {
console.error(
`${LOG_PREFIX} - Loading of element <${elementTag}> failed, please provide <ng-template #error>Loading failed...</ng-template> and reference it in *axLazyElement="errorTemplate: error" to display customized error message in place of element`
);
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,24 @@ describe('LazyElementsLoaderService', () => {
});
});

it('rejects promise once element bundle loading failed', done => {
const promise = service.loadElement(
'http://elements.com/some-element',
'some-element'
);

appendChildSpy.calls.argsFor(0)[0].onerror('404');

promise
.then(() => {
fail('should reject promise instead');
})
.catch(error => {
expect(error).toBe('404');
done();
});
});

it('adds a script tag without module type', () => {
service.loadElement('http://elements.com/some-element', 'some-element');

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,19 @@ export class LazyElementsLoaderService {
script.type = 'module';
}
script.src = url;
script.onload = notifier;
script.onload = notifier.resolve;
script.onerror = notifier.reject;
document.body.appendChild(script);
}

return this.registry.get(this.stripUrlProtocol(url));
}

private addElement(url: string): () => void {
let notifier;
private addElement(url: string): Notifier {
let notifier: Notifier;
this.registry.set(
this.stripUrlProtocol(url),
new Promise<void>(resolve => (notifier = resolve))
new Promise<void>((resolve, reject) => (notifier = { resolve, reject }))
);
return notifier;
}
Expand All @@ -56,3 +57,8 @@ export class LazyElementsLoaderService {
return url.replace(/https?:\/\//, '');
}
}

interface Notifier {
resolve: () => void;
reject: (error: any) => void;
}

0 comments on commit 3fa7246

Please sign in to comment.