Angular NgZone Use Case

I was recently working on a project that loaded an iFrame into an Angular component's template file. The source of this iFrame is generated by a third party who uses Chase to validate payment information, and I was integrating the third party tool into our web app. One key aspect of generating this iFrame required that we provide the url to a callback file (provided by the vendor), which their iFrame would use to control flow, like changing the look of the buttons on the iFrame, but calling functions in the callback file, that would need to trigger function we added on window.top. The problem seemed relative straight forward, until I started to work on the flow out of the iFrame and this is where NgZone comes in.

Issues

  • One functionality of the iFrame is to validate that correct credit card (CC) information is entered, and upon failing to enter this data, we wanted to show a modal with the reasons for failure, but the modal was taking incredibly long to show up
  • Upon entering valid payment information, the iFrame logic would validate this through Chase and call a function the callback file to redirect back to the home page, but even though the redirect via router.navigate was working, the styles and loading of data in the home page would be painfully slow
  • Even after being rerouted back to the home page successfully, other options in the page, such as tabs, were not responsive, and if they did change pages, the data in those pages would be missing
  • If you just allows the page to sit, after a while the data would load and the styles would load, and the page would look normal, but it was too long

First solution

Initially, it seemed like using tick() from ApplicationRef to "explicitly process change detection and its side-effects". This worked like a charm for the modals, and instead of them taking forever to load upon the iFrame submission detecting an error, it was as quick as expected. I thought I had won this war. However, when submitting the iFrame successfully and being redirected to the home page, I found that the slow loading issue continued! 🤯

Second Solution

This is when NgZone came into play. Looking back, it makes sense that this is the Angular service I needed to use, because it is a "...service for executing work inside or outside of the Angular zone". In my case, when the iFrame made the call to Chase to validate the payment information, succeeded or failed, and returned to call a function in the vendor provider callback file, that callback file was living outside of the Angular world. The callback file lives in a publicly available location, e.g. /assets/html so that the Chase iFrame can access it. Therefore, when the iFrame calls a function this callback file, that file is outside of Angular and needs to be told to run inside. Here is how this works for my use case.

i. In my angular component, I imported NgZone in the constructor:

constructor(
    private zone: NgZone,
    @Inject('Window') private window: Window
){}

ii. The functions that the callback file needed to execute, not only had to go on window.top, but needed to be wrapped the NgZone:

private setupWindowFunctions(){	(
	this.window as { [key: string]: any })['funct1'] = (res: VenRes) => {
		this.zone.run(() => {
		this.func1(res); 
	});
};

Now, when the iFrame comes back with a successful validation or error, their callback file on our web app's public folder, triggers the window.top function, such as func1, and since this function lives within the NgZone, it is executed seamlessly, avoiding the slow data load that I was seeing before.

I think is is a nugget of knowledge that only experienced Angular developers might know of the top of their hear, so hopefully it helps someone out there, cause I certainly did not know this and own it to my awesome team to have figured it out.

Show Comments