-
-
Save maumchaves/d7270b54afd5c8ae120f34b41436a119 to your computer and use it in GitHub Desktop.
| /* | |
| * USAGE | |
| * | |
| * Add the following element in your app component template: | |
| * | |
| * <ng-container move-fixed-content-with-toast></ng-container> | |
| * | |
| * IMPLEMENTATION NOTES | |
| * | |
| * - It works with only one toast at the time. | |
| * | |
| */ | |
| import { Directive, OnInit, OnDestroy } from '@angular/core'; | |
| import { App } from 'ionic-angular'; | |
| @Directive({ | |
| selector: '[move-fixed-content-with-toast]' | |
| }) | |
| export class MoveFixedContentWithToastDirective implements OnInit, OnDestroy { | |
| private ionAppElem: any; | |
| private observer: MutationObserver; | |
| constructor(private app: App) {} | |
| ngOnInit() { | |
| this.ionAppElem = document.querySelector('.app-root'); | |
| this.observer = new MutationObserver(this.mutationCallback); | |
| this.observer.observe(this.ionAppElem, { childList: true }); | |
| this.app.viewDidEnter.subscribe(() => { | |
| this.moveFixedContentsUp(this.getToastElem(), true); | |
| }); | |
| } | |
| ngOnDestroy() { | |
| this.observer.disconnect(); | |
| } | |
| private getToastElem() { | |
| return document.querySelector('.toast-wrapper.toast-bottom'); | |
| } | |
| private mutationCallback = mutationsList => { | |
| for (const mutation of mutationsList) { | |
| const toastElem = this.getToastElem(); | |
| if (mutation.type == 'childList' && toastElem) { | |
| this.moveFixedContentsUp(toastElem); | |
| this.setToastObserver(toastElem); | |
| } | |
| } | |
| }; | |
| private restoreFixedContents(toastBottomWrapperElem: any) { | |
| const fixedContents = this.getFixedContents(); | |
| for (const fixed of fixedContents) { | |
| const marginBottom = parseInt(fixed.style.marginBottom); | |
| fixed.style.transition = 'margin-bottom 400ms'; | |
| fixed.style.marginBottom = `${marginBottom - | |
| toastBottomWrapperElem.offsetHeight}px`; | |
| const timeout = setTimeout(() => { | |
| fixed && (fixed.style.transition = 'initial'); | |
| clearTimeout(timeout); | |
| }, 410); | |
| fixed.removeAttribute('moved-by-toast'); | |
| } | |
| } | |
| private setToastObserver(toastBottomElem: any) { | |
| const toastObserver = new MutationObserver(mutationsList => { | |
| if (toastBottomElem.style.transform === 'translateY(100%)') { | |
| this.restoreFixedContents(toastBottomElem); | |
| toastObserver.disconnect(); | |
| } | |
| }); | |
| toastObserver.observe(toastBottomElem, { | |
| attributes: true | |
| }); | |
| } | |
| private getFixedContents(onlyUntouched?: boolean) { | |
| const result = onlyUntouched | |
| ? document.querySelectorAll( | |
| '.ion-page .fixed-content:not([moved-by-toast=true])' | |
| ) | |
| : document.querySelectorAll('.ion-page .fixed-content'); | |
| return [].slice.call(result); | |
| } | |
| private moveFixedContentsUp(toastBottomElem: any, onlyUntouched?: boolean) { | |
| if (!toastBottomElem) return; | |
| const fixedContents = this.getFixedContents(onlyUntouched); | |
| for (const fixed of fixedContents) { | |
| if (!onlyUntouched) { | |
| fixed.style.transition = 'margin-bottom 400ms'; | |
| fixed.setAttribute('moved-by-toast', true); | |
| } | |
| const marginBottom = parseInt(fixed.style.marginBottom); | |
| fixed.style.marginBottom = `${marginBottom + | |
| toastBottomElem.offsetHeight}px`; | |
| } | |
| } | |
| } |
Got it to work but noticed that if multiple pages (same component) are in history moveFixedContentsUp is triggered more than once shifting ion-fab more than it should.
@shyamal890 what do you mean with multiple pages in the same component? Can you give me more context about "shifting ion-fab more than it should"?
In my case, I am using it in a page with Tabs, in which each Tab is a "different page". If both pages (tabs) are already loaded, the directive will update both of them so in case you change the page very fast so that the toast hasn't been completely hidden yet (in case you are using dismissOnPageChange: true), or you change the page and you expect the toast to be visible in the new page, the new fixed-content "position" will be properly updated so the transition and animation in the new open page when the toast is dismissed will still be smoothly.
So when you are going to a new page and you have a toast (even when this is being sliding out), the directive will try to properly update the fixed-content "position" in that new page, and there is where the directive call the moveFixedContentsUp again, but it is supposed to only update all those fixed-content that hasn't been updated yet. Once the toast is dismissed, all the fixed-content are restored as expected.
Additional implementation note: (I'll add these limitations in the code comments)
- This directive is aimed to work with only one toast at the time.
Not able to make it work, can you please provide a working example in stackblitz?