MOBILE-4163 siteplugins: Fix lifecycle overrides

main
Noel De Martin 2022-10-24 14:17:24 +02:00
parent 153c8a6d02
commit 06a2b23adb
3 changed files with 33 additions and 3 deletions

View File

@ -3,3 +3,5 @@ this.CoreSitesProvider.getSite().then(site => {
document.getElementById('username').innerText = `, ${username}`; document.getElementById('username').innerText = `, ${username}`;
}); });
this.ngAfterViewInit = () => this.CoreDomUtilsProvider.showToast('Lifecycle hook called');

View File

@ -173,6 +173,8 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy, DoCheck {
// Create the component, using the text as the template. // Create the component, using the text as the template.
return class CoreCompileHtmlFakeComponent implements OnInit, AfterContentInit, AfterViewInit, OnDestroy { return class CoreCompileHtmlFakeComponent implements OnInit, AfterContentInit, AfterViewInit, OnDestroy {
private ongoingLifecycleHooks: Set<keyof AfterViewInit | keyof AfterContentInit | keyof OnDestroy> = new Set();
constructor() { constructor() {
// Store this instance so it can be accessed by the outer component. // Store this instance so it can be accessed by the outer component.
compileInstance.componentInstance = this; compileInstance.componentInstance = this;
@ -222,21 +224,41 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy, DoCheck {
* Content has been initialized. * Content has been initialized.
*/ */
ngAfterContentInit(): void { ngAfterContentInit(): void {
// To be overridden. this.callLifecycleHookOverride('ngAfterContentInit');
} }
/** /**
* View has been initialized. * View has been initialized.
*/ */
ngAfterViewInit(): void { ngAfterViewInit(): void {
// To be overridden. this.callLifecycleHookOverride('ngAfterViewInit');
} }
/** /**
* Component destroyed. * Component destroyed.
*/ */
ngOnDestroy(): void { ngOnDestroy(): void {
// To be overridden. this.callLifecycleHookOverride('ngOnDestroy');
}
/**
* Call a lifecycle method that can be overriden in plugins.
*
* This is necessary because overriding lifecycle hooks at runtime does not work in Angular. This may be happening
* because lifecycle hooks are special methods treated by the Angular compiler, so it is possible that it's storing
* a reference to the method defined during compilation. In order to work around that, this will call the actual method
* from the plugin without causing infinite loops in case it wasn't overriden.
*
* @param method Lifecycle hook method name.
*/
private callLifecycleHookOverride(method: keyof AfterViewInit | keyof AfterContentInit | keyof OnDestroy): void {
if (this.ongoingLifecycleHooks.has(method)) {
return;
}
this.ongoingLifecycleHooks.add(method);
this[method]();
this.ongoingLifecycleHooks.delete(method);
} }
}; };

View File

@ -13,3 +13,9 @@ Feature: Plugins work properly.
When I press "Moodle App Behat (auto-generated)" in the app When I press "Moodle App Behat (auto-generated)" in the app
Then I should find "studentusername" in the app Then I should find "studentusername" in the app
Scenario: Use lifecycle hooks
Given I entered the app as "studentusername"
When I press the more menu button in the app
And I press "Moodle App Behat (auto-generated)" in the app
Then I should find "Lifecycle hook called" in the app