Skip to content

Commit 590c927

Browse files
authored
Add onLoad and onError event emitters (#128)
* Add onLoad and onError event emitters Emit events on onload and onerror of the <img> underlying <cl-image>. Update photo_album sample. Fixes #81
1 parent ebbff80 commit 590c927

File tree

5 files changed

+84
-14
lines changed

5 files changed

+84
-14
lines changed

samples/photo_album/app/js/photo-list/photo-list.component.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,16 @@
1111
[public-id]="publicId"
1212
type="facebook"
1313
angle="20"
14+
(onLoad)="onLoadImage($event)"
1415
>
1516
<cl-transformation effect="art:hokusai"></cl-transformation>
1617
<cl-transformation border="3px_solid_rgb:00390b" radius="20"></cl-transformation>
1718
</cl-image>
19+
<cl-image
20+
public-id="non-existing"
21+
(onError)="onErrorImage($event)"
22+
>
23+
</cl-image>
1824
</a>
1925
</div>
2026

samples/photo_album/app/js/photo-list/photo-list.component.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@ export class PhotoListComponent implements OnInit {
2222
}
2323

2424
changePublicId() {
25-
this.publicId = (this.publicId === 'officialchucknorrispage') ? 'billclinton' : 'officialchucknorrispage';
25+
this.publicId = (this.publicId === 'officialchucknorrispage') ? 'billclinton' : 'officialchucknorrispage';
26+
}
27+
28+
onLoadImage(success) {
29+
console.log('On load', success);
30+
}
31+
onErrorImage(err) {
32+
console.log('On error!!', err);
2633
}
2734
}

src/cloudinary-image.component.spec.ts

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,52 @@ describe('CloudinaryImage', () => {
220220
});
221221
});
222222

223+
describe('event emitters', () => {
224+
let onImageLoad;
225+
let onImageError;
226+
let des: DebugElement; // the elements w/ the directive
227+
228+
@Component({
229+
template: `<cl-image id="image1" [public-id]="publicId"></cl-image>`
230+
})
231+
class TestComponent {
232+
publicId: string = 'sample';
233+
}
234+
235+
let fixture: ComponentFixture<TestComponent>;
236+
237+
beforeEach(() => {
238+
fixture = TestBed.configureTestingModule({
239+
declarations: [CloudinaryTransformationDirective, CloudinaryImage, TestComponent],
240+
providers: [{ provide: Cloudinary, useValue: localCloudinary }]
241+
}).createComponent(TestComponent);
242+
243+
fixture.detectChanges(); // initial binding
244+
// all elements with an attached CloudinaryImage
245+
des = fixture.debugElement.query(By.directive(CloudinaryImage));
246+
onImageLoad = jasmine.createSpy('onImageLoad');
247+
onImageError = jasmine.createSpy('onImageError');
248+
des.componentInstance.onLoad.subscribe(onImageLoad);
249+
des.componentInstance.onError.subscribe(onImageError);
250+
});
251+
252+
it('calls the onLoad callback when image loads successfully', () => {
253+
// Simulate the load event
254+
const img = des.children[0].nativeElement as HTMLImageElement;
255+
img.dispatchEvent(new Event('load'));
256+
expect(onImageLoad).toHaveBeenCalled();
257+
expect(onImageError).not.toHaveBeenCalled();
258+
});
259+
260+
it('calls the onError callback when image fails to load', () => {
261+
// Simulate the error event
262+
const img = des.children[0].nativeElement as HTMLImageElement;
263+
img.dispatchEvent(new CustomEvent('error', { detail: 'Eitan was here' }));
264+
expect(onImageLoad).not.toHaveBeenCalled();
265+
expect(onImageError).toHaveBeenCalled();
266+
});
267+
});
268+
223269
describe('responsive images with nested transformations using the cld-responsive attribute', () => {
224270
@Component({
225271
template: `<cl-image cld-responsive id="image1" public-id="responsive_sample.jpg">
@@ -254,5 +300,4 @@ describe('CloudinaryImage', () => {
254300
/c_scale,l_text:roboto_25_bold:SDK,w_300\/e_art:hokusai\/f_auto\/responsive_sample.jpg/));
255301
});
256302
});
257-
258303
});

src/cloudinary-image.component.ts

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
import {
2-
Component,
3-
ElementRef,
4-
Input,
5-
ContentChildren,
6-
QueryList,
7-
AfterViewInit,
8-
OnInit,
9-
OnChanges,
10-
SimpleChanges,
11-
OnDestroy,
2+
Component,
3+
ElementRef,
4+
EventEmitter,
5+
Input,
6+
Output,
7+
ContentChildren,
8+
QueryList,
9+
AfterViewInit,
10+
OnInit,
11+
OnChanges,
12+
SimpleChanges,
13+
OnDestroy
1214
} from '@angular/core';
1315
import { Cloudinary } from './cloudinary.service';
1416
import { CloudinaryTransformationDirective } from './cloudinary-transformation.directive';
@@ -24,6 +26,9 @@ export class CloudinaryImage
2426
@ContentChildren(CloudinaryTransformationDirective)
2527
transformations: QueryList<CloudinaryTransformationDirective>;
2628

29+
@Output() onLoad: EventEmitter<boolean> = new EventEmitter(); // Callback when an image is loaded successfully
30+
@Output() onError: EventEmitter<boolean> = new EventEmitter(); // Callback when an image is loaded with error
31+
2732
observer: MutationObserver;
2833

2934
constructor(private el: ElementRef, private cloudinary: Cloudinary) {}
@@ -55,7 +60,7 @@ export class CloudinaryImage
5560
}
5661

5762
ngOnDestroy(): void {
58-
if (this.observer) {
63+
if (this.observer && this.observer.disconnect) {
5964
this.observer.disconnect();
6065
}
6166
}
@@ -75,6 +80,13 @@ export class CloudinaryImage
7580
}
7681
const nativeElement = this.el.nativeElement;
7782
const image = nativeElement.children[0];
83+
// Add onload and onerror handlers
84+
image.onload = e => {
85+
this.onLoad.emit(e);
86+
}
87+
image.onerror = e => {
88+
this.onError.emit(e);
89+
}
7890
const options = this.cloudinary.toCloudinaryAttributes(
7991
nativeElement.attributes,
8092
this.transformations

src/cloudinary-video.component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ export class CloudinaryVideo
5555
}
5656

5757
ngOnDestroy(): void {
58-
if (this.observer) {
58+
if (this.observer && this.observer.disconnect) {
5959
this.observer.disconnect();
6060
}
6161
}

0 commit comments

Comments
 (0)