Skip to content

Instantly share code, notes, and snippets.

@joelkesler
Last active September 9, 2025 18:27
Show Gist options
  • Select an option

  • Save joelkesler/6760e79b5000ca99657b8023698b6051 to your computer and use it in GitHub Desktop.

Select an option

Save joelkesler/6760e79b5000ca99657b8023698b6051 to your computer and use it in GitHub Desktop.
iFrame on Unload Directive (for Angular v20 and up) - Track when an iframe url changes
import { Directive, ElementRef, OnInit, OnDestroy, inject, output } from '@angular/core';
/**
* This directive is designed to monitor iframe navigation or reloads by listening to the `unload` event
* on the iframe's `contentWindow`. It emits an `iframeUnload` output event, allowing parent components
* to react to changes in the iframe's content.
*
* Note: Due to cross-origin restrictions, the directive may not work if the iframe loads content from
* a different domain. In such cases, a warning is logged to the console.
*
* Usage:
* ```html
* <iframe appIframeUnload (iframeUnload)="getIframeLocation()"></iframe>
* ```
*
* ```ts
* @Component({
* selector: 'app-example',
* //...
* })
* export class ExampleComponent
* //...
*
* iframe = viewChild.required<ElementRef>('iframe');
*
* getIframeLocation() {
* const iframeElement = this.iframe().nativeElement;
* if (iframeElement && iframeElement.contentWindow) {
* const newLocation = iframeElement.contentWindow.location;
* console.log('Iframe location:', newLocation.href);
* }
* }
* }
* ```
*
* @selector iframe[appIframeUnload]
* @standalone
*/
@Directive({
selector: 'iframe[appIframeUnload]',
standalone: true,
})
export class IframeUnloadDirective implements OnInit, OnDestroy {
private el = inject(ElementRef<HTMLIFrameElement>);
iframeUnload = output<void>();
ngOnInit() {
const iframe = this.el.nativeElement;
iframe.onload = () => {
try {
iframe.contentWindow.onunload = () => {
// Use setTimeout to ensure the iframe has time to update its location
setTimeout(() => {
this.iframeUnload.emit();
}, 0);
};
} catch (e) {
console.warn(
'IframeUnloadDirective: Could not attach unload listener to iframe (likely cross-origin):',
e,
);
}
};
}
ngOnDestroy() {
const iframe = this.el.nativeElement;
if (iframe.contentWindow) {
iframe.contentWindow.onunload = null;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment