diff --git a/src/core/directives/collapsible-footer.ts b/src/core/directives/collapsible-footer.ts index 7ead926a9..f0b7c90ad 100644 --- a/src/core/directives/collapsible-footer.ts +++ b/src/core/directives/collapsible-footer.ts @@ -50,6 +50,9 @@ export class CoreCollapsibleFooterDirective implements OnInit, OnDestroy { protected endContentScrollListener?: EventListener; protected resizeListener?: CoreEventObserver; protected slotPromise?: CoreCancellablePromise; + protected calcPending = false; + protected pageDidEnterListener?: EventListener; + protected page?: HTMLElement; constructor(el: ElementRef, protected ionContent: IonContent) { this.element = el.nativeElement; @@ -82,6 +85,14 @@ export class CoreCollapsibleFooterDirective implements OnInit, OnDestroy { * Calculate the height of the footer. */ protected async calculateHeight(): Promise { + if (!CoreDom.isElementVisible(this.element)) { + this.calcPending = true; + + return; + } + + this.calcPending = false; + this.element.classList.remove('is-active'); await CoreUtils.nextTick(); @@ -159,6 +170,16 @@ export class CoreCollapsibleFooterDirective implements OnInit, OnDestroy { this.resizeListener = CoreDom.onWindowResize(() => { this.calculateHeight(); }, 50); + + this.page = this.content.closest('.ion-page') || undefined; + this.page?.addEventListener( + 'ionViewDidEnter', + this.pageDidEnterListener = () => { + if (this.calcPending) { + this.calculateHeight(); + } + }, + ); } /** @@ -228,6 +249,9 @@ export class CoreCollapsibleFooterDirective implements OnInit, OnDestroy { if (this.content && this.endContentScrollListener) { this.content.removeEventListener('ionScrollEnd', this.endContentScrollListener); } + if (this.page && this.pageDidEnterListener) { + this.page.removeEventListener('ionViewDidEnter', this.pageDidEnterListener); + } this.resizeListener?.off(); this.slotPromise?.cancel(); diff --git a/src/core/directives/collapsible-header.ts b/src/core/directives/collapsible-header.ts index 1cb15b1d6..19da86802 100644 --- a/src/core/directives/collapsible-header.ts +++ b/src/core/directives/collapsible-header.ts @@ -77,6 +77,8 @@ export class CoreCollapsibleHeaderDirective implements OnInit, OnChanges, OnDest protected isWithinContent = false; protected enteredPromise = new CorePromisedValue(); protected mutationObserver?: MutationObserver; + protected firstEnter = true; + protected initPending = false; constructor(el: ElementRef) { this.collapsedHeader = el.nativeElement; @@ -145,14 +147,19 @@ export class CoreCollapsibleHeaderDirective implements OnInit, OnChanges, OnDest this.page.addEventListener( 'ionViewDidEnter', this.pageDidEnterListener = () => { - clearTimeout(timeout); - this.enteredPromise.resolve(); + if (this.firstEnter) { + this.firstEnter = false; + clearTimeout(timeout); + this.enteredPromise.resolve(); + } else if (this.initPending) { + this.initializeFloatingTitle(); + } }, - { once: true }, ); // Timeout in case event is never fired. const timeout = window.setTimeout(() => { + this.firstEnter = false; this.enteredPromise.reject(new Error('[collapsible-header] Waiting for ionViewDidEnter timeout reached')); }, 5000); @@ -259,6 +266,14 @@ export class CoreCollapsibleHeaderDirective implements OnInit, OnChanges, OnDest throw new Error('[collapsible-header] Couldn\'t create floating title'); } + if (!CoreDom.isElementVisible(this.expandedHeader)) { + this.initPending = true; + + return; + } + + this.initPending = false; + this.page.classList.remove('collapsible-header-page-is-active'); CoreUtils.nextTick(); diff --git a/src/core/directives/collapsible-item.ts b/src/core/directives/collapsible-item.ts index 3bac8a97c..6e95242f2 100644 --- a/src/core/directives/collapsible-item.ts +++ b/src/core/directives/collapsible-item.ts @@ -56,6 +56,9 @@ export class CoreCollapsibleItemDirective implements OnInit, OnDestroy { protected darkModeListener?: Subscription; protected domPromise?: CoreCancellablePromise; protected uniqueId: string; + protected calcPending = false; + protected pageDidEnterListener?: EventListener; + protected page?: HTMLElement; constructor(el: ElementRef) { this.element = el.nativeElement; @@ -93,6 +96,15 @@ export class CoreCollapsibleItemDirective implements OnInit, OnDestroy { await this.calculateHeight(); + this.page?.addEventListener( + 'ionViewDidEnter', + this.pageDidEnterListener = () => { + if (this.calcPending) { + this.calculateHeight(); + } + }, + ); + this.resizeListener = CoreDom.onWindowResize(() => { this.calculateHeight(); }, 50); @@ -112,13 +124,12 @@ export class CoreCollapsibleItemDirective implements OnInit, OnDestroy { await this.domPromise; - const page = this.element.closest('.ion-page'); - - if (!page) { + this.page = this.element.closest('.ion-page') || undefined; + if (!this.page) { return; } - await CoreComponentsRegistry.waitComponentsReady(page, 'core-loading', CoreLoadingComponent); + await CoreComponentsRegistry.waitComponentsReady(this.page, 'core-loading', CoreLoadingComponent); } /** @@ -137,6 +148,15 @@ export class CoreCollapsibleItemDirective implements OnInit, OnDestroy { await this.waitFormatTextsRendered(); + if (!this.element.clientHeight) { + this.calcPending = true; + this.element.classList.remove('collapsible-loading-height'); + + return; + } + + this.calcPending = false; + this.expandedHeight = this.element.getBoundingClientRect().height; // Restore the max height now. @@ -278,6 +298,10 @@ export class CoreCollapsibleItemDirective implements OnInit, OnDestroy { this.resizeListener?.off(); this.darkModeListener?.unsubscribe(); this.domPromise?.cancel(); + + if (this.page && this.pageDidEnterListener) { + this.page.removeEventListener('ionViewDidEnter', this.pageDidEnterListener); + } } }