diff --git a/angular/src/directives/overlays/modal.ts b/angular/src/directives/overlays/modal.ts index 10f1120906..5db8c6749d 100644 --- a/angular/src/directives/overlays/modal.ts +++ b/angular/src/directives/overlays/modal.ts @@ -54,6 +54,7 @@ export declare interface IonModal extends Components.IonModal { @ProxyCmp({ inputs: [ 'animated', + 'keepContentsMounted', 'backdropBreakpoint', 'backdropDismiss', 'breakpoints', @@ -78,9 +79,12 @@ export declare interface IonModal extends Components.IonModal { @Component({ selector: 'ion-modal', changeDetection: ChangeDetectionStrategy.OnPush, - template: `
`, + template: `
+ +
`, inputs: [ 'animated', + 'keepContentsMounted', 'backdropBreakpoint', 'backdropDismiss', 'breakpoints', diff --git a/angular/src/directives/overlays/popover.ts b/angular/src/directives/overlays/popover.ts index 0bcf5f7e26..aedbb97f9c 100644 --- a/angular/src/directives/overlays/popover.ts +++ b/angular/src/directives/overlays/popover.ts @@ -51,6 +51,7 @@ export declare interface IonPopover extends Components.IonPopover { 'alignment', 'animated', 'arrow', + 'keepContentsMounted', 'backdropDismiss', 'cssClass', 'dismissOnSelect', @@ -73,11 +74,12 @@ export declare interface IonPopover extends Components.IonPopover { @Component({ selector: 'ion-popover', changeDetection: ChangeDetectionStrategy.OnPush, - template: ``, + template: ``, inputs: [ 'alignment', 'animated', 'arrow', + 'keepContentsMounted', 'backdropDismiss', 'cssClass', 'dismissOnSelect', diff --git a/angular/test/test-app/e2e/src/keep-contents-mounted.spec.ts b/angular/test/test-app/e2e/src/keep-contents-mounted.spec.ts new file mode 100644 index 0000000000..a4bc99167f --- /dev/null +++ b/angular/test/test-app/e2e/src/keep-contents-mounted.spec.ts @@ -0,0 +1,60 @@ +describe('overlays - keepContentsMounted', () => { + describe('modal', () => { + it('should not mount component if false', () => { + cy.visit('/modal-inline'); + + cy.get('ion-modal ion-content').should('not.exist'); + }); + + it('should mount component if true', () => { + cy.visit('/keep-contents-mounted'); + + cy.get('ion-modal ion-content').should('exist'); + }); + + it('should keep component mounted after dismissing if true', () => { + cy.visit('/keep-contents-mounted'); + + cy.get('#open-modal').click(); + + cy.get('ion-modal ion-content').should('exist'); + + cy.get('ion-modal ion-button').click(); + + cy.get('ion-modal') + .should('not.be.visible') + .should('have.class', 'overlay-hidden'); + + cy.get('ion-modal ion-content').should('exist'); + }); + }) + describe('popover', () => { + it('should not mount component if false', () => { + cy.visit('/popover-inline'); + + cy.get('ion-popover ion-content').should('not.exist'); + }); + + it('should mount component if true', () => { + cy.visit('/keep-contents-mounted'); + + cy.get('ion-popover ion-content').should('exist'); + }); + + it('should keep component mounted after dismissing if true', () => { + cy.visit('/keep-contents-mounted'); + + cy.get('#open-popover').click(); + + cy.get('ion-popover ion-content').should('exist'); + + cy.get('ion-popover ion-button').click(); + + cy.get('ion-popover') + .should('not.be.visible') + .should('have.class', 'overlay-hidden'); + + cy.get('ion-popover ion-content').should('exist'); + }); + }); +}); diff --git a/angular/test/test-app/e2e/src/popover.spec.ts b/angular/test/test-app/e2e/src/popover.spec.ts index abf1c06fa1..17f8fe6445 100644 --- a/angular/test/test-app/e2e/src/popover.spec.ts +++ b/angular/test/test-app/e2e/src/popover.spec.ts @@ -4,10 +4,17 @@ describe('Popovers: Inline', () => { }); it('should initially have no items', () => { + cy.get('ion-button').click(); + + cy.get('ion-popover').should('be.visible'); cy.get('ion-list ion-item').should('not.exist'); }); it('should have items after 1500ms', () => { + cy.get('ion-button').click(); + + cy.get('ion-popover').should('be.visible'); + cy.wait(1500); cy.get('ion-list ion-item:nth-child(1)').should('have.text', 'A'); diff --git a/angular/test/test-app/src/app/app-routing.module.ts b/angular/test/test-app/src/app/app-routing.module.ts index be5ad94bb5..6ffdfd8d32 100644 --- a/angular/test/test-app/src/app/app-routing.module.ts +++ b/angular/test/test-app/src/app/app-routing.module.ts @@ -31,6 +31,7 @@ const routes: Routes = [ { path: 'modals', component: ModalComponent }, { path: 'modal-inline', loadChildren: () => import('./modal-inline').then(m => m.ModalInlineModule) }, { path: 'view-child', component: ViewChildComponent }, + { path: 'keep-contents-mounted', loadChildren: () => import('./keep-contents-mounted').then(m => m.OverlayAutoMountModule) }, { path: 'popover-inline', loadChildren: () => import('./popover-inline').then(m => m.PopoverInlineModule) }, { path: 'providers', component: ProvidersComponent }, { path: 'router-link', component: RouterLinkComponent }, diff --git a/angular/test/test-app/src/app/keep-contents-mounted/index.ts b/angular/test/test-app/src/app/keep-contents-mounted/index.ts new file mode 100644 index 0000000000..c949db9a98 --- /dev/null +++ b/angular/test/test-app/src/app/keep-contents-mounted/index.ts @@ -0,0 +1,2 @@ +export * from './keep-contents-mounted.component'; +export * from './keep-contents-mounted.module'; diff --git a/angular/test/test-app/src/app/keep-contents-mounted/keep-contents-mounted-routing.module.ts b/angular/test/test-app/src/app/keep-contents-mounted/keep-contents-mounted-routing.module.ts new file mode 100644 index 0000000000..e453cb212e --- /dev/null +++ b/angular/test/test-app/src/app/keep-contents-mounted/keep-contents-mounted-routing.module.ts @@ -0,0 +1,16 @@ +import { NgModule } from "@angular/core"; +import { RouterModule } from "@angular/router"; +import { OverlayKeepContentsMounted } from "."; + +@NgModule({ + imports: [ + RouterModule.forChild([ + { + path: '', + component: OverlayKeepContentsMounted + } + ]) + ], + exports: [RouterModule] +}) +export class OverlayKeepContentsMountedRoutingModule { } diff --git a/angular/test/test-app/src/app/keep-contents-mounted/keep-contents-mounted.component.html b/angular/test/test-app/src/app/keep-contents-mounted/keep-contents-mounted.component.html new file mode 100644 index 0000000000..8311ecd5a7 --- /dev/null +++ b/angular/test/test-app/src/app/keep-contents-mounted/keep-contents-mounted.component.html @@ -0,0 +1,22 @@ + + Open Modal + Open Popover + + + + + Dismiss + Modal Content + + + + + + + + Dismiss + Popover Content + + + + diff --git a/angular/test/test-app/src/app/keep-contents-mounted/keep-contents-mounted.component.ts b/angular/test/test-app/src/app/keep-contents-mounted/keep-contents-mounted.component.ts new file mode 100644 index 0000000000..ccf0e90165 --- /dev/null +++ b/angular/test/test-app/src/app/keep-contents-mounted/keep-contents-mounted.component.ts @@ -0,0 +1,13 @@ +import { Component } from "@angular/core"; + +/** + * Validates that inline modals correctly mount + * inner components when keepContentsMounted is + * enabled. + */ +@Component({ + selector: 'app-keep-contents-mounted', + templateUrl: 'keep-contents-mounted.component.html' +}) +export class OverlayKeepContentsMounted { +} diff --git a/angular/test/test-app/src/app/keep-contents-mounted/keep-contents-mounted.module.ts b/angular/test/test-app/src/app/keep-contents-mounted/keep-contents-mounted.module.ts new file mode 100644 index 0000000000..265e850126 --- /dev/null +++ b/angular/test/test-app/src/app/keep-contents-mounted/keep-contents-mounted.module.ts @@ -0,0 +1,12 @@ +import { CommonModule } from "@angular/common"; +import { NgModule } from "@angular/core"; +import { IonicModule } from "@ionic/angular"; +import { OverlayKeepContentsMountedRoutingModule } from "./keep-contents-mounted-routing.module"; +import { OverlayKeepContentsMounted } from "./keep-contents-mounted.component"; + +@NgModule({ + imports: [CommonModule, IonicModule, OverlayKeepContentsMountedRoutingModule], + declarations: [OverlayKeepContentsMounted], + exports: [OverlayKeepContentsMounted] +}) +export class OverlayAutoMountModule { } diff --git a/angular/test/test-app/src/app/popover-inline/popover-inline.component.html b/angular/test/test-app/src/app/popover-inline/popover-inline.component.html index 1de4bc20af..f4f311646c 100644 --- a/angular/test/test-app/src/app/popover-inline/popover-inline.component.html +++ b/angular/test/test-app/src/app/popover-inline/popover-inline.component.html @@ -1,4 +1,6 @@ - +Open Popover + + diff --git a/angular/test/test-app/src/app/popover-inline/popover-inline.component.ts b/angular/test/test-app/src/app/popover-inline/popover-inline.component.ts index d162795795..36e472900c 100644 --- a/angular/test/test-app/src/app/popover-inline/popover-inline.component.ts +++ b/angular/test/test-app/src/app/popover-inline/popover-inline.component.ts @@ -1,4 +1,4 @@ -import { AfterViewInit, Component } from "@angular/core"; +import { Component } from "@angular/core"; /** * Validates that inline popovers will correctly display @@ -9,11 +9,13 @@ import { AfterViewInit, Component } from "@angular/core"; selector: 'app-popover-inline', templateUrl: 'popover-inline.component.html' }) -export class PopoverInlineComponent implements AfterViewInit { +export class PopoverInlineComponent { items: string[] = []; - ngAfterViewInit(): void { + openPopover(popover: HTMLIonPopoverElement) { + popover.present(); + setTimeout(() => { this.items = ['A', 'B', 'C', 'D']; }, 1000); diff --git a/core/api.txt b/core/api.txt index e72c296273..dec444946d 100644 --- a/core/api.txt +++ b/core/api.txt @@ -776,6 +776,7 @@ ion-modal,prop,handle,boolean | undefined,undefined,false,false ion-modal,prop,htmlAttributes,undefined | { [key: string]: any; },undefined,false,false ion-modal,prop,initialBreakpoint,number | undefined,undefined,false,false ion-modal,prop,isOpen,boolean,false,false,false +ion-modal,prop,keepContentsMounted,boolean,false,false,false ion-modal,prop,keyboardClose,boolean,true,false,false ion-modal,prop,leaveAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false ion-modal,prop,mode,"ios" | "md",undefined,false,false @@ -895,6 +896,7 @@ ion-popover,prop,enterAnimation,((baseEl: any, opts?: any) => Animation) | undef ion-popover,prop,event,any,undefined,false,false ion-popover,prop,htmlAttributes,undefined | { [key: string]: any; },undefined,false,false ion-popover,prop,isOpen,boolean,false,false,false +ion-popover,prop,keepContentsMounted,boolean,false,false,false ion-popover,prop,keyboardClose,boolean,true,false,false ion-popover,prop,leaveAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false ion-popover,prop,mode,"ios" | "md",undefined,false,false diff --git a/core/src/components.d.ts b/core/src/components.d.ts index 5e4041c3f8..cd73b59f2a 100644 --- a/core/src/components.d.ts +++ b/core/src/components.d.ts @@ -1571,6 +1571,10 @@ export namespace Components { * If `true`, the modal will open. If `false`, the modal will close. Use this if you need finer grained control over presentation, otherwise just use the modalController or the `trigger` property. Note: `isOpen` will not automatically be set back to `false` when the modal dismisses. You will need to do that in your code. */ "isOpen": boolean; + /** + * If `true`, the component passed into `ion-modal` will automatically be mounted when the modal is created. The component will remain mounted even when the modal is dismissed. However, the component will be destroyed when the modal is destroyed. This property is not reactive and should only be used when initially creating a modal. Note: This feature only applies to inline modals in JavaScript frameworks such as Angular, React, and Vue. + */ + "keepContentsMounted": boolean; /** * If `true`, the keyboard will be automatically dismissed when the overlay is presented. */ @@ -1940,6 +1944,10 @@ export namespace Components { * If `true`, the popover will open. If `false`, the popover will close. Use this if you need finer grained control over presentation, otherwise just use the popoverController or the `trigger` property. Note: `isOpen` will not automatically be set back to `false` when the popover dismisses. You will need to do that in your code. */ "isOpen": boolean; + /** + * If `true`, the component passed into `ion-popover` will automatically be mounted when the popover is created. The component will remain mounted even when the popover is dismissed. However, the component will be destroyed when the popover is destroyed. This property is not reactive and should only be used when initially creating a popover. Note: This feature only applies to inline popovers in JavaScript frameworks such as Angular, React, and Vue. + */ + "keepContentsMounted": boolean; /** * If `true`, the keyboard will be automatically dismissed when the overlay is presented. */ @@ -5488,6 +5496,10 @@ declare namespace LocalJSX { * If `true`, the modal will open. If `false`, the modal will close. Use this if you need finer grained control over presentation, otherwise just use the modalController or the `trigger` property. Note: `isOpen` will not automatically be set back to `false` when the modal dismisses. You will need to do that in your code. */ "isOpen"?: boolean; + /** + * If `true`, the component passed into `ion-modal` will automatically be mounted when the modal is created. The component will remain mounted even when the modal is dismissed. However, the component will be destroyed when the modal is destroyed. This property is not reactive and should only be used when initially creating a modal. Note: This feature only applies to inline modals in JavaScript frameworks such as Angular, React, and Vue. + */ + "keepContentsMounted"?: boolean; /** * If `true`, the keyboard will be automatically dismissed when the overlay is presented. */ @@ -5779,6 +5791,10 @@ declare namespace LocalJSX { * If `true`, the popover will open. If `false`, the popover will close. Use this if you need finer grained control over presentation, otherwise just use the popoverController or the `trigger` property. Note: `isOpen` will not automatically be set back to `false` when the popover dismisses. You will need to do that in your code. */ "isOpen"?: boolean; + /** + * If `true`, the component passed into `ion-popover` will automatically be mounted when the popover is created. The component will remain mounted even when the popover is dismissed. However, the component will be destroyed when the popover is destroyed. This property is not reactive and should only be used when initially creating a popover. Note: This feature only applies to inline popovers in JavaScript frameworks such as Angular, React, and Vue. + */ + "keepContentsMounted"?: boolean; /** * If `true`, the keyboard will be automatically dismissed when the overlay is presented. */ diff --git a/core/src/components/modal/modal.tsx b/core/src/components/modal/modal.tsx index 766423a948..873a414818 100644 --- a/core/src/components/modal/modal.tsx +++ b/core/src/components/modal/modal.tsx @@ -222,6 +222,19 @@ export class Modal implements ComponentInterface, OverlayInterface { this.configureTriggerInteraction(); } + /** + * If `true`, the component passed into `ion-modal` will + * automatically be mounted when the modal is created. The + * component will remain mounted even when the modal is dismissed. + * However, the component will be destroyed when the modal is + * destroyed. This property is not reactive and should only be + * used when initially creating a modal. + * + * Note: This feature only applies to inline modals in JavaScript + * frameworks such as Angular, React, and Vue. + */ + @Prop() keepContentsMounted = false; + /** * TODO (FW-937) * This needs to default to true in the next diff --git a/core/src/components/popover/popover.tsx b/core/src/components/popover/popover.tsx index 4237443911..e9d6bacfc9 100644 --- a/core/src/components/popover/popover.tsx +++ b/core/src/components/popover/popover.tsx @@ -253,6 +253,19 @@ export class Popover implements ComponentInterface, PopoverInterface { } } + /** + * If `true`, the component passed into `ion-popover` will + * automatically be mounted when the popover is created. The + * component will remain mounted even when the popover is dismissed. + * However, the component will be destroyed when the popover is + * destroyed. This property is not reactive and should only be + * used when initially creating a popover. + * + * Note: This feature only applies to inline popovers in JavaScript + * frameworks such as Angular, React, and Vue. + */ + @Prop() keepContentsMounted = false; + /** * Emitted after the popover has presented. */ diff --git a/packages/react/src/components/createInlineOverlayComponent.tsx b/packages/react/src/components/createInlineOverlayComponent.tsx index 783ba5b495..2851a371b8 100644 --- a/packages/react/src/components/createInlineOverlayComponent.tsx +++ b/packages/react/src/components/createInlineOverlayComponent.tsx @@ -21,6 +21,7 @@ interface IonicReactInternalProps extends React.HTMLAttributes) => void; onWillDismiss?: (event: CustomEvent) => void; onWillPresent?: (event: CustomEvent) => void; + keepContentsMounted?: boolean; } export const createInlineOverlayComponent = ( @@ -128,7 +129,7 @@ export const createInlineOverlayComponent = ( * so conditionally render the component * based on the isOpen state. */ - return createElement(tagName, newProps, (this.state.isOpen) ? + return createElement(tagName, newProps, (this.state.isOpen || this.props.keepContentsMounted) ? createElement('div', { id: 'ion-react-wrapper', ref: this.wrapperRef, diff --git a/packages/react/test-app/cypress/integration/overlay-components/KeepContentsMounted.spec.ts b/packages/react/test-app/cypress/integration/overlay-components/KeepContentsMounted.spec.ts new file mode 100644 index 0000000000..b466e0e753 --- /dev/null +++ b/packages/react/test-app/cypress/integration/overlay-components/KeepContentsMounted.spec.ts @@ -0,0 +1,60 @@ +describe('keepContentsMounted', () => { + describe('modal', () => { + it('should not mount component if false', () => { + cy.visit('/overlay-components/modal'); + + cy.get('ion-modal ion-content').should('not.exist'); + }); + + it('should mount component if true', () => { + cy.visit('/keep-contents-mounted'); + + cy.get('ion-modal ion-content').should('exist'); + }); + + it('should keep component mounted after dismissing if true', () => { + cy.visit('/keep-contents-mounted'); + + cy.get('#open-modal').click(); + + cy.get('ion-modal ion-content').should('exist'); + + cy.get('ion-modal ion-button').click(); + + cy.get('ion-modal') + .should('not.be.visible') + .should('have.class', 'overlay-hidden'); + + cy.get('ion-modal ion-content').should('exist'); + }); + }) + describe('popover', () => { + it('should not mount component if false', () => { + cy.visit('/overlay-components/popover'); + + cy.get('ion-popover ion-content').should('not.exist'); + }); + + it('should mount component if true', () => { + cy.visit('/keep-contents-mounted'); + + cy.get('ion-popover ion-content').should('exist'); + }); + + it('should keep component mounted after dismissing if true', () => { + cy.visit('/keep-contents-mounted'); + + cy.get('#open-popover').click(); + + cy.get('ion-popover ion-content').should('exist'); + + cy.get('ion-popover ion-button').click(); + + cy.get('ion-popover') + .should('not.be.visible') + .should('have.class', 'overlay-hidden'); + + cy.get('ion-popover ion-content').should('exist'); + }); + }) +}); diff --git a/packages/react/test-app/src/App.tsx b/packages/react/test-app/src/App.tsx index 11cb79fba1..c499afbf9f 100644 --- a/packages/react/test-app/src/App.tsx +++ b/packages/react/test-app/src/App.tsx @@ -24,6 +24,7 @@ import './theme/variables.css'; import Main from './pages/Main'; import OverlayHooks from './pages/overlay-hooks/OverlayHooks'; import OverlayComponents from './pages/overlay-components/OverlayComponents'; +import KeepContentsMounted from './pages/overlay-components/KeepContentsMounted'; import Tabs from './pages/Tabs'; setupIonicReact(); @@ -35,6 +36,7 @@ const App: React.FC = () => ( + diff --git a/packages/react/test-app/src/pages/Main.tsx b/packages/react/test-app/src/pages/Main.tsx index 944ac25419..f4800b69db 100644 --- a/packages/react/test-app/src/pages/Main.tsx +++ b/packages/react/test-app/src/pages/Main.tsx @@ -31,6 +31,11 @@ const Main: React.FC = () => { Overlay Components + + + Keep Contents Mounted Overlay Components + + Tabs diff --git a/packages/react/test-app/src/pages/overlay-components/KeepContentsMounted.tsx b/packages/react/test-app/src/pages/overlay-components/KeepContentsMounted.tsx new file mode 100644 index 0000000000..8f4e852737 --- /dev/null +++ b/packages/react/test-app/src/pages/overlay-components/KeepContentsMounted.tsx @@ -0,0 +1,38 @@ +import React, { useState } from 'react'; +import { + IonButton, + IonContent, + IonPage, + IonModal, + IonPopover, +} from '@ionic/react'; + +const KeepContentsMounted: React.FC = () => { + const [showModal, setShowModal] = useState(false); + const [showPopover, setShowPopover] = useState(false); + + return ( + + + setShowModal(true)}>Open Modal + setShowPopover(true)}>Open Popover + + setShowPopover(false)}> + + setShowModal(false)}>Dismiss + Modal Content + + + + setShowPopover(false)}> + + setShowPopover(false)}>Dismiss + Popover Content + + + + + ); +}; + +export default KeepContentsMounted; diff --git a/packages/vue/src/components/Overlays.ts b/packages/vue/src/components/Overlays.ts index 95f40dda76..a5f9d104a9 100644 --- a/packages/vue/src/components/Overlays.ts +++ b/packages/vue/src/components/Overlays.ts @@ -29,7 +29,7 @@ export const IonPicker = /*@__PURE__*/ defineOverlayContainer('io export const IonToast = /*@__PURE__*/ defineOverlayContainer('ion-toast', defineIonToastCustomElement, ['animated', 'buttons', 'color', 'cssClass', 'duration', 'enterAnimation', 'header', 'htmlAttributes', 'icon', 'keyboardClose', 'leaveAnimation', 'message', 'mode', 'position', 'translucent'], toastController); -export const IonModal = /*@__PURE__*/ defineOverlayContainer('ion-modal', defineIonModalCustomElement, ['animated', 'backdropBreakpoint', 'backdropDismiss', 'breakpoints', 'canDismiss', 'enterAnimation', 'handle', 'htmlAttributes', 'initialBreakpoint', 'isOpen', 'keyboardClose', 'leaveAnimation', 'mode', 'presentingElement', 'showBackdrop', 'swipeToClose', 'trigger']); +export const IonModal = /*@__PURE__*/ defineOverlayContainer('ion-modal', defineIonModalCustomElement, ['animated', 'backdropBreakpoint', 'backdropDismiss', 'breakpoints', 'canDismiss', 'enterAnimation', 'handle', 'htmlAttributes', 'initialBreakpoint', 'isOpen', 'keepContentsMounted', 'keyboardClose', 'leaveAnimation', 'mode', 'presentingElement', 'showBackdrop', 'swipeToClose', 'trigger']); -export const IonPopover = /*@__PURE__*/ defineOverlayContainer('ion-popover', defineIonPopoverCustomElement, ['alignment', 'animated', 'arrow', 'backdropDismiss', 'component', 'componentProps', 'dismissOnSelect', 'enterAnimation', 'event', 'htmlAttributes', 'isOpen', 'keyboardClose', 'leaveAnimation', 'mode', 'reference', 'showBackdrop', 'side', 'size', 'translucent', 'trigger', 'triggerAction']); +export const IonPopover = /*@__PURE__*/ defineOverlayContainer('ion-popover', defineIonPopoverCustomElement, ['alignment', 'animated', 'arrow', 'backdropDismiss', 'component', 'componentProps', 'dismissOnSelect', 'enterAnimation', 'event', 'htmlAttributes', 'isOpen', 'keepContentsMounted', 'keyboardClose', 'leaveAnimation', 'mode', 'reference', 'showBackdrop', 'side', 'size', 'translucent', 'trigger', 'triggerAction']); diff --git a/packages/vue/src/vue-component-lib/overlays.ts b/packages/vue/src/vue-component-lib/overlays.ts index a59e72d7b5..ede3ac4a37 100644 --- a/packages/vue/src/vue-component-lib/overlays.ts +++ b/packages/vue/src/vue-component-lib/overlays.ts @@ -162,7 +162,7 @@ export const defineOverlayContainer = (name: string, defin return h( name, { ...restOfProps, ref: elementRef }, - (isOpen.value) ? slots : undefined + (isOpen.value || restOfProps.keepContentsMounted) ? slots : undefined ) } }); diff --git a/packages/vue/test-app/src/components/PopoverContent.vue b/packages/vue/test-app/src/components/PopoverContent.vue index 8a3717968d..94534e57da 100644 --- a/packages/vue/test-app/src/components/PopoverContent.vue +++ b/packages/vue/test-app/src/components/PopoverContent.vue @@ -1,11 +1,16 @@ diff --git a/packages/vue/test-app/tests/e2e/specs/overlays-keep-contents-mounted.js b/packages/vue/test-app/tests/e2e/specs/overlays-keep-contents-mounted.js new file mode 100644 index 0000000000..269f3fc25c --- /dev/null +++ b/packages/vue/test-app/tests/e2e/specs/overlays-keep-contents-mounted.js @@ -0,0 +1,52 @@ +describe('overlays - keepContentsMounted', () => { + beforeEach(() => { + cy.viewport(1000, 900); + cy.visit('http://localhost:8080/keep-contents-mounted') + }) + describe('modal', () => { + it('should not mount component if false', () => { + cy.get('ion-modal#default-modal ion-content').should('not.exist'); + }); + + it('should mount component if true', () => { + cy.get('ion-modal#auto-mount-modal ion-content').should('exist'); + }); + + it('should keep component mounted after dismissing if true', () => { + cy.get('#open-auto-mount-modal').click(); + + cy.get('ion-modal#auto-mount-modal ion-content').should('exist'); + + cy.get('ion-modal#auto-mount-modal #dismiss').click(); + + cy.get('ion-modal#auto-mount-modal') + .should('not.be.visible') + .should('have.class', 'overlay-hidden'); + + cy.get('ion-modal#auto-mount-modal ion-content').should('exist'); + }); + }) + describe('popover', () => { + it('should not mount component if false', () => { + cy.get('ion-popover#default-popover ion-content').should('not.exist'); + }); + + it('should mount component if true', () => { + cy.get('ion-popover#auto-mount-popover ion-content').should('exist'); + }); + + it('should keep component mounted after dismissing if true', () => { + cy.get('#open-auto-mount-popover').click(); + + cy.get('ion-popover#auto-mount-popover ion-content').should('exist'); + + cy.get('ion-popover#auto-mount-popover #dismiss').click(); + + cy.get('ion-popover#auto-mount-popover') + .should('not.be.visible') + .should('have.class', 'overlay-hidden'); + + cy.get('ion-popover#auto-mount-popover ion-content').should('exist'); + }); + }) +}) diff --git a/packages/vue/test-app/tests/e2e/specs/overlays.js b/packages/vue/test-app/tests/e2e/specs/overlays.js index 5026fd244a..fcb0360d3b 100644 --- a/packages/vue/test-app/tests/e2e/specs/overlays.js +++ b/packages/vue/test-app/tests/e2e/specs/overlays.js @@ -134,7 +134,7 @@ describe('Overlays', () => { cy.get('ion-button#present-overlay').click(); cy.get('ion-popover.ion-popover-controller').should('exist'); - cy.get('ion-popover.ion-popover-controller ion-content').should('have.text', 'Custom Title'); + cy.get('ion-popover.ion-popover-controller ion-content #title').should('have.text', 'Custom Title'); }); it('should pass props to popover via component', () => { @@ -144,7 +144,7 @@ describe('Overlays', () => { cy.get('ion-button#present-overlay').click(); cy.get('ion-popover').should('exist'); - cy.get('ion-popover.popover-inline ion-content').should('have.text', 'Custom Title'); + cy.get('ion-popover.popover-inline ion-content #title').should('have.text', 'Custom Title'); }); it('should only open one instance at a time when props change quickly on component', () => {