From 34ad92f2d74a5ab8389001e99e064a2228da49a0 Mon Sep 17 00:00:00 2001 From: Sean Perkins Date: Tue, 12 Sep 2023 12:31:28 -0400 Subject: [PATCH 1/5] docs(modal): angular playground examples --- docs/api/modal.md | 12 +++ .../child-state/angular/app_module_ts.md | 19 ++++ .../angular/child_component_html.md | 24 +++++ .../child-state/angular/child_component_ts.md | 22 +++++ .../angular/example_component_html.md | 23 +++++ .../angular/example_component_ts.md | 58 ++++++++++++ .../modal/can-dismiss/child-state/demo.html | 92 +++++++++++++++++++ .../v7/modal/can-dismiss/child-state/index.md | 30 ++++++ .../v7/modal/can-dismiss/child-state/react.md | 85 +++++++++++++++++ .../v7/modal/can-dismiss/child-state/vue.md | 78 ++++++++++++++++ 10 files changed, 443 insertions(+) create mode 100644 static/usage/v7/modal/can-dismiss/child-state/angular/app_module_ts.md create mode 100644 static/usage/v7/modal/can-dismiss/child-state/angular/child_component_html.md create mode 100644 static/usage/v7/modal/can-dismiss/child-state/angular/child_component_ts.md create mode 100644 static/usage/v7/modal/can-dismiss/child-state/angular/example_component_html.md create mode 100644 static/usage/v7/modal/can-dismiss/child-state/angular/example_component_ts.md create mode 100644 static/usage/v7/modal/can-dismiss/child-state/demo.html create mode 100644 static/usage/v7/modal/can-dismiss/child-state/index.md create mode 100644 static/usage/v7/modal/can-dismiss/child-state/react.md create mode 100644 static/usage/v7/modal/can-dismiss/child-state/vue.md diff --git a/docs/api/modal.md b/docs/api/modal.md index c0eb448318a..9bc25674960 100644 --- a/docs/api/modal.md +++ b/docs/api/modal.md @@ -87,6 +87,18 @@ import CanDismissPreventSwipeToCloseExample from '@site/static/usage/v7/modal/ca +### Modifying dismiss behavior in child components + +In certain scenarios, developers may need to customize the behavior of the `canDismiss` callback based on the state of a presented modal. This customization can be particularly useful, for instance, when developers want to prevent the modal from being dismissed if a form within it is invalid. + +To achieve this customization, child components can employ various techniques such as function callbacks, event emission, or other reactivity mechanisms to communicate with the parent component and update the conditions governing the `canDismiss` callback. + +Here's a simplified example illustrating how a child component can interact with a parent component to modify the `canDismiss` callback: + +import CanDismissChildStateExample from '@site/static/usage/v7/modal/can-dismiss/child-state/index.md'; + + + ## Types of modals ### Card Modal diff --git a/static/usage/v7/modal/can-dismiss/child-state/angular/app_module_ts.md b/static/usage/v7/modal/can-dismiss/child-state/angular/app_module_ts.md new file mode 100644 index 00000000000..b273d851f90 --- /dev/null +++ b/static/usage/v7/modal/can-dismiss/child-state/angular/app_module_ts.md @@ -0,0 +1,19 @@ +```ts +import { NgModule } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { BrowserModule } from '@angular/platform-browser'; +import { RouterModule } from '@angular/router'; + +import { IonicModule } from '@ionic/angular'; + +import { AppComponent } from './app.component'; +import { ExampleComponent } from './example.component'; +import { ChildComponent } from './child.component'; + +@NgModule({ + imports: [BrowserModule, FormsModule, RouterModule.forRoot([]), IonicModule.forRoot({})], + declarations: [AppComponent, ExampleComponent, ChildComponent], + bootstrap: [AppComponent], +}) +export class AppModule {} +``` diff --git a/static/usage/v7/modal/can-dismiss/child-state/angular/child_component_html.md b/static/usage/v7/modal/can-dismiss/child-state/angular/child_component_html.md new file mode 100644 index 00000000000..3bef90bc0f9 --- /dev/null +++ b/static/usage/v7/modal/can-dismiss/child-state/angular/child_component_html.md @@ -0,0 +1,24 @@ +```html +
+ + + Modal + + Close + + + + + + + + Override Dismiss
+ Toggle the checkbox to allow immediately dismissing the modal without a prompt. +
+
+
+
+
+``` diff --git a/static/usage/v7/modal/can-dismiss/child-state/angular/child_component_ts.md b/static/usage/v7/modal/can-dismiss/child-state/angular/child_component_ts.md new file mode 100644 index 00000000000..420359602a2 --- /dev/null +++ b/static/usage/v7/modal/can-dismiss/child-state/angular/child_component_ts.md @@ -0,0 +1,22 @@ +```ts +import { Component, Input, Output, EventEmitter } from '@angular/core'; + +import { CheckboxCustomEvent, IonModal } from '@ionic/angular'; + +@Component({ + selector: 'app-child', + templateUrl: 'child.component.html', +}) +export class ChildComponent { + @Input() modal!: IonModal; + + @Output() dismissChange = new EventEmitter(); + + checkboxChanged(event: any) { + const ev = event as CheckboxCustomEvent; + const checked = ev.detail.checked; + + this.dismissChange.emit(checked); + } +} +``` diff --git a/static/usage/v7/modal/can-dismiss/child-state/angular/example_component_html.md b/static/usage/v7/modal/can-dismiss/child-state/angular/example_component_html.md new file mode 100644 index 00000000000..2b19ce97b50 --- /dev/null +++ b/static/usage/v7/modal/can-dismiss/child-state/angular/example_component_html.md @@ -0,0 +1,23 @@ +```html +
+ + + App + + + + Open + + + + + + +
+``` diff --git a/static/usage/v7/modal/can-dismiss/child-state/angular/example_component_ts.md b/static/usage/v7/modal/can-dismiss/child-state/angular/example_component_ts.md new file mode 100644 index 00000000000..19544ec574a --- /dev/null +++ b/static/usage/v7/modal/can-dismiss/child-state/angular/example_component_ts.md @@ -0,0 +1,58 @@ +```ts +import { Component } from '@angular/core'; + +import { ActionSheetController } from '@ionic/angular'; + +@Component({ + selector: 'app-example', + templateUrl: 'example.component.html', +}) +export class ExampleComponent { + presentingElement = undefined; + + private canDismissOverride = false; + + constructor(private actionSheetCtrl: ActionSheetController) {} + + ngOnInit() { + this.presentingElement = document.querySelector('.ion-page'); + } + + onDismissChange(canDismiss: boolean) { + // Allows the modal to be dismissed based on the state of the checkbox + this.canDismissOverride = canDismiss; + } + + onWillPresent() { + // Resets the override when the modal is presented + this.canDismissOverride = false; + } + + canDismiss = async () => { + if (this.canDismissOverride) { + // Checks for the override flag to return early if we can dismiss the overlay immediately + return true; + } + + const actionSheet = await this.actionSheetCtrl.create({ + header: 'Are you sure?', + buttons: [ + { + text: 'Yes', + role: 'confirm', + }, + { + text: 'No', + role: 'cancel', + }, + ], + }); + + actionSheet.present(); + + const { role } = await actionSheet.onWillDismiss(); + + return role === 'confirm'; + }; +} +``` diff --git a/static/usage/v7/modal/can-dismiss/child-state/demo.html b/static/usage/v7/modal/can-dismiss/child-state/demo.html new file mode 100644 index 00000000000..3d8398d22ba --- /dev/null +++ b/static/usage/v7/modal/can-dismiss/child-state/demo.html @@ -0,0 +1,92 @@ + + + + + + Modal | Can Dismiss + + + + + + + + +
+ + + App + + + + Open + + + + + Modal + + Close + + + + + + + + Override Dismiss
+ Toggle the checkbox to allow immediately dismissing the modal without a prompt. +
+
+
+
+
+
+
+
+ + + + diff --git a/static/usage/v7/modal/can-dismiss/child-state/index.md b/static/usage/v7/modal/can-dismiss/child-state/index.md new file mode 100644 index 00000000000..a1956ed1656 --- /dev/null +++ b/static/usage/v7/modal/can-dismiss/child-state/index.md @@ -0,0 +1,30 @@ +import Playground from '@site/src/components/global/Playground'; + +import vue from './vue.md'; + +import react from './react.md'; + +import angular_example_component_html from './angular/example_component_html.md'; +import angular_example_component_ts from './angular/example_component_ts.md'; +import angular_child_component_html from './angular/child_component_html.md'; +import angular_child_component_ts from './angular/child_component_ts.md'; +import angular_app_module_ts from './angular/app_module_ts.md'; + + diff --git a/static/usage/v7/modal/can-dismiss/child-state/react.md b/static/usage/v7/modal/can-dismiss/child-state/react.md new file mode 100644 index 00000000000..9ef7f6f682b --- /dev/null +++ b/static/usage/v7/modal/can-dismiss/child-state/react.md @@ -0,0 +1,85 @@ +```tsx +import React, { useState, useRef, useEffect } from 'react'; +import { + IonButtons, + IonButton, + IonModal, + IonHeader, + IonContent, + IonToolbar, + IonTitle, + IonPage, + useIonActionSheet, +} from '@ionic/react'; + +function Example() { + const modal = useRef(null); + const page = useRef(null); + + const [presentingElement, setPresentingElement] = useState(null); + const [present] = useIonActionSheet(); + + useEffect(() => { + setPresentingElement(page.current); + }, []); + + function dismiss() { + modal.current?.dismiss(); + } + + function canDismiss() { + return new Promise((resolve, reject) => { + present({ + header: 'Are you sure?', + buttons: [ + { + text: 'Yes', + role: 'confirm', + }, + { + text: 'No', + role: 'cancel', + }, + ], + onWillDismiss: (ev) => { + if (ev.detail.role === 'confirm') { + resolve(true); + } else { + reject(); + } + }, + }); + }); + } + + return ( + + + + App + + + + + Open + + + + + Modal + + dismiss()}>Close + + + + +

You will be prompted when closing this modal.

+
+
+
+
+ ); +} + +export default Example; +``` diff --git a/static/usage/v7/modal/can-dismiss/child-state/vue.md b/static/usage/v7/modal/can-dismiss/child-state/vue.md new file mode 100644 index 00000000000..cdf51c892ac --- /dev/null +++ b/static/usage/v7/modal/can-dismiss/child-state/vue.md @@ -0,0 +1,78 @@ +```html + + + +``` From ae27a4c27735f375e4e5c034269e46a8ca773343 Mon Sep 17 00:00:00 2001 From: Sean Perkins Date: Tue, 12 Sep 2023 12:43:40 -0400 Subject: [PATCH 2/5] docs(modal): react playground examples --- .../v7/modal/can-dismiss/child-state/index.md | 10 +++- .../child-state/react/child_tsx.md | 55 +++++++++++++++++++ .../{react.md => react/main_tsx.md} | 39 ++++++++----- 3 files changed, 89 insertions(+), 15 deletions(-) create mode 100644 static/usage/v7/modal/can-dismiss/child-state/react/child_tsx.md rename static/usage/v7/modal/can-dismiss/child-state/{react.md => react/main_tsx.md} (65%) diff --git a/static/usage/v7/modal/can-dismiss/child-state/index.md b/static/usage/v7/modal/can-dismiss/child-state/index.md index a1956ed1656..1bb6ac38438 100644 --- a/static/usage/v7/modal/can-dismiss/child-state/index.md +++ b/static/usage/v7/modal/can-dismiss/child-state/index.md @@ -2,7 +2,8 @@ import Playground from '@site/src/components/global/Playground'; import vue from './vue.md'; -import react from './react.md'; +import react_main_tsx from './react/main_tsx.md'; +import react_child_tsx from './react/child_tsx.md'; import angular_example_component_html from './angular/example_component_html.md'; import angular_example_component_ts from './angular/example_component_ts.md'; @@ -13,7 +14,12 @@ import angular_app_module_ts from './angular/app_module_ts.md'; void; + dismiss: () => void; +} + +function Child({ dismissChange, dismiss }: ChildProps) { + const checkboxChanged = (ev: CheckboxCustomEvent) => { + const checked = ev.detail.checked; + dismissChange(checked); + }; + + return ( + <> + + + Modal + + dismiss()}>Close + + + + + + + + Override Dismiss +
+ + Toggle the checkbox to allow immediately dismissing the modal without a prompt. + +
+
+
+
+ + ); +} +export default Child; +``` diff --git a/static/usage/v7/modal/can-dismiss/child-state/react.md b/static/usage/v7/modal/can-dismiss/child-state/react/main_tsx.md similarity index 65% rename from static/usage/v7/modal/can-dismiss/child-state/react.md rename to static/usage/v7/modal/can-dismiss/child-state/react/main_tsx.md index 9ef7f6f682b..2f0cf5dbb3b 100644 --- a/static/usage/v7/modal/can-dismiss/child-state/react.md +++ b/static/usage/v7/modal/can-dismiss/child-state/react/main_tsx.md @@ -12,9 +12,12 @@ import { useIonActionSheet, } from '@ionic/react'; +import Child from './Child'; + function Example() { const modal = useRef(null); const page = useRef(null); + const [canDismissOverride, setCanDismissOverride] = useState(false); const [presentingElement, setPresentingElement] = useState(null); const [present] = useIonActionSheet(); @@ -27,7 +30,16 @@ function Example() { modal.current?.dismiss(); } - function canDismiss() { + function onWillPresent() { + // Resets the override when the modal is presented + setCanDismissOverride(false); + } + + async function canDismiss() { + if (canDismissOverride) { + // Checks for the override flag to return early if we can dismiss the overlay immediately + return true; + } return new Promise((resolve, reject) => { present({ header: 'Are you sure?', @@ -63,18 +75,19 @@ function Example() { Open - - - - Modal - - dismiss()}>Close - - - - -

You will be prompted when closing this modal.

-
+ + { + setCanDismissOverride(checked); + }} + /> From f0675da9dcb194a9defb029f079048502518f772 Mon Sep 17 00:00:00 2001 From: Sean Perkins Date: Tue, 12 Sep 2023 13:09:30 -0400 Subject: [PATCH 3/5] docs(modal): vue playground examples --- .../v7/modal/can-dismiss/child-state/index.md | 10 ++- .../v7/modal/can-dismiss/child-state/vue.md | 78 ----------------- .../can-dismiss/child-state/vue/child_vue.md | 51 +++++++++++ .../child-state/vue/example_vue.md | 85 +++++++++++++++++++ 4 files changed, 144 insertions(+), 80 deletions(-) delete mode 100644 static/usage/v7/modal/can-dismiss/child-state/vue.md create mode 100644 static/usage/v7/modal/can-dismiss/child-state/vue/child_vue.md create mode 100644 static/usage/v7/modal/can-dismiss/child-state/vue/example_vue.md diff --git a/static/usage/v7/modal/can-dismiss/child-state/index.md b/static/usage/v7/modal/can-dismiss/child-state/index.md index 1bb6ac38438..d213d283663 100644 --- a/static/usage/v7/modal/can-dismiss/child-state/index.md +++ b/static/usage/v7/modal/can-dismiss/child-state/index.md @@ -1,6 +1,7 @@ import Playground from '@site/src/components/global/Playground'; -import vue from './vue.md'; +import vue_example_vue from './vue/example_vue.md'; +import vue_child_vue from './vue/child_vue.md'; import react_main_tsx from './react/main_tsx.md'; import react_child_tsx from './react/child_tsx.md'; @@ -20,7 +21,12 @@ import angular_app_module_ts from './angular/app_module_ts.md'; 'src/Child.tsx': react_child_tsx, }, }, - vue, + vue: { + files: { + 'src/components/Example.vue': vue_example_vue, + 'src/components/Child.vue': vue_child_vue, + }, + }, angular: { files: { 'src/app/example.component.html': angular_example_component_html, diff --git a/static/usage/v7/modal/can-dismiss/child-state/vue.md b/static/usage/v7/modal/can-dismiss/child-state/vue.md deleted file mode 100644 index cdf51c892ac..00000000000 --- a/static/usage/v7/modal/can-dismiss/child-state/vue.md +++ /dev/null @@ -1,78 +0,0 @@ -```html - - - -``` diff --git a/static/usage/v7/modal/can-dismiss/child-state/vue/child_vue.md b/static/usage/v7/modal/can-dismiss/child-state/vue/child_vue.md new file mode 100644 index 00000000000..6c402f88a98 --- /dev/null +++ b/static/usage/v7/modal/can-dismiss/child-state/vue/child_vue.md @@ -0,0 +1,51 @@ +```html + + + +``` diff --git a/static/usage/v7/modal/can-dismiss/child-state/vue/example_vue.md b/static/usage/v7/modal/can-dismiss/child-state/vue/example_vue.md new file mode 100644 index 00000000000..831c89cb435 --- /dev/null +++ b/static/usage/v7/modal/can-dismiss/child-state/vue/example_vue.md @@ -0,0 +1,85 @@ +```html + + + +``` From 1d4ca449e21e544e128a7e36f9d2fec748243744 Mon Sep 17 00:00:00 2001 From: Sean Perkins Date: Tue, 12 Sep 2023 14:22:59 -0400 Subject: [PATCH 4/5] chore: clean-up --- static/usage/v7/modal/can-dismiss/child-state/react/main_tsx.md | 1 - 1 file changed, 1 deletion(-) diff --git a/static/usage/v7/modal/can-dismiss/child-state/react/main_tsx.md b/static/usage/v7/modal/can-dismiss/child-state/react/main_tsx.md index 2f0cf5dbb3b..d8db547e7f9 100644 --- a/static/usage/v7/modal/can-dismiss/child-state/react/main_tsx.md +++ b/static/usage/v7/modal/can-dismiss/child-state/react/main_tsx.md @@ -1,7 +1,6 @@ ```tsx import React, { useState, useRef, useEffect } from 'react'; import { - IonButtons, IonButton, IonModal, IonHeader, From 4def4fbbab3d9cbc94f71dadbd08894d82b7632a Mon Sep 17 00:00:00 2001 From: Sean Perkins <13732623+sean-perkins@users.noreply.github.com> Date: Wed, 13 Sep 2023 11:34:33 -0400 Subject: [PATCH 5/5] Update static/usage/v7/modal/can-dismiss/child-state/angular/example_component_html.md Co-authored-by: Shawn Taylor --- .../can-dismiss/child-state/angular/example_component_html.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/usage/v7/modal/can-dismiss/child-state/angular/example_component_html.md b/static/usage/v7/modal/can-dismiss/child-state/angular/example_component_html.md index 2b19ce97b50..aeed41b7408 100644 --- a/static/usage/v7/modal/can-dismiss/child-state/angular/example_component_html.md +++ b/static/usage/v7/modal/can-dismiss/child-state/angular/example_component_html.md @@ -12,7 +12,7 @@ trigger="open-modal" [canDismiss]="canDismiss" [presentingElement]="presentingElement" - (willPresent)="onWilPresent()" + (willPresent)="onWillPresent()" >