mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-11-10 00:27:41 +08:00
feat(action-sheet): add data property to ActionSheetButton (#23744)
resolves #23700 Co-authored-by: Liam DeBeasi <liamdebeasi@icloud.com>
This commit is contained in:
@ -23,7 +23,7 @@ ion-accordion-group,event,ionChange,AccordionGroupChangeEventDetail<any>,true
|
||||
ion-action-sheet,scoped
|
||||
ion-action-sheet,prop,animated,boolean,true,false,false
|
||||
ion-action-sheet,prop,backdropDismiss,boolean,true,false,false
|
||||
ion-action-sheet,prop,buttons,(string | ActionSheetButton)[],[],false,false
|
||||
ion-action-sheet,prop,buttons,(string | ActionSheetButton<any>)[],[],false,false
|
||||
ion-action-sheet,prop,cssClass,string | string[] | undefined,undefined,false,false
|
||||
ion-action-sheet,prop,enterAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
|
||||
ion-action-sheet,prop,header,string | undefined,undefined,false,false
|
||||
|
||||
@ -16,11 +16,12 @@ export interface ActionSheetOptions {
|
||||
leaveAnimation?: AnimationBuilder;
|
||||
}
|
||||
|
||||
export interface ActionSheetButton {
|
||||
export interface ActionSheetButton<T = any> {
|
||||
text?: string;
|
||||
role?: 'cancel' | 'destructive' | 'selected' | string;
|
||||
icon?: string;
|
||||
cssClass?: string | string[];
|
||||
id?: string;
|
||||
handler?: () => boolean | void | Promise<boolean | void>;
|
||||
data?: T;
|
||||
}
|
||||
|
||||
@ -156,11 +156,11 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
|
||||
private async buttonClick(button: ActionSheetButton) {
|
||||
const role = button.role;
|
||||
if (isCancel(role)) {
|
||||
return this.dismiss(undefined, role);
|
||||
return this.dismiss(button.data, role);
|
||||
}
|
||||
const shouldDismiss = await this.callButtonHandler(button);
|
||||
if (shouldDismiss) {
|
||||
return this.dismiss(undefined, button.role);
|
||||
return this.dismiss(button.data, button.role);
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
@ -6,6 +6,8 @@ An Action Sheet is a dialog that displays a set of options. It appears on top of
|
||||
|
||||
A button's `role` property can either be `destructive` or `cancel`. Buttons without a role property will have the default look for the platform. Buttons with the `cancel` role will always load as the bottom button, no matter where they are in the array. All other buttons will be displayed in the order they have been added to the `buttons` array. Note: We recommend that `destructive` buttons are always the first button in the array, making them the top button. Additionally, if the action sheet is dismissed by tapping the backdrop, then it will fire the handler from the button with the cancel role.
|
||||
|
||||
A button can also be passed data via the `data` property on `ActionSheetButton`. This will populate the `data` field in the return value of the `onDidDismiss` method.
|
||||
|
||||
## Customization
|
||||
|
||||
Action Sheet uses scoped encapsulation, which means it will automatically scope its CSS by appending each of the styles with an additional class at runtime. Overriding scoped selectors in CSS requires a [higher specificity](https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity) selector.
|
||||
@ -39,12 +41,13 @@ Any of the defined [CSS Custom Properties](#css-custom-properties) can be used t
|
||||
### ActionSheetButton
|
||||
|
||||
```typescript
|
||||
interface ActionSheetButton {
|
||||
interface ActionSheetButton<T = any> {
|
||||
text?: string;
|
||||
role?: 'cancel' | 'destructive' | 'selected' | string;
|
||||
icon?: string;
|
||||
cssClass?: string | string[];
|
||||
handler?: () => boolean | void | Promise<boolean | void>;
|
||||
data?: T;
|
||||
}
|
||||
```
|
||||
|
||||
@ -97,18 +100,23 @@ export class ActionSheetExample {
|
||||
role: 'destructive',
|
||||
icon: 'trash',
|
||||
id: 'delete-button',
|
||||
data: {
|
||||
type: 'delete'
|
||||
},
|
||||
handler: () => {
|
||||
console.log('Delete clicked');
|
||||
}
|
||||
}, {
|
||||
text: 'Share',
|
||||
icon: 'share',
|
||||
data: 10,
|
||||
handler: () => {
|
||||
console.log('Share clicked');
|
||||
}
|
||||
}, {
|
||||
text: 'Play (open modal)',
|
||||
icon: 'caret-forward-circle',
|
||||
data: 'Data value',
|
||||
handler: () => {
|
||||
console.log('Play clicked');
|
||||
}
|
||||
@ -129,8 +137,8 @@ export class ActionSheetExample {
|
||||
});
|
||||
await actionSheet.present();
|
||||
|
||||
const { role } = await actionSheet.onDidDismiss();
|
||||
console.log('onDidDismiss resolved with role', role);
|
||||
const { role, data } = await actionSheet.onDidDismiss();
|
||||
console.log('onDidDismiss resolved with role and data', role, data);
|
||||
}
|
||||
|
||||
}
|
||||
@ -155,18 +163,23 @@ async function presentActionSheet() {
|
||||
role: 'destructive',
|
||||
icon: 'trash',
|
||||
id: 'delete-button',
|
||||
data: {
|
||||
type: 'delete'
|
||||
},
|
||||
handler: () => {
|
||||
console.log('Delete clicked');
|
||||
}
|
||||
}, {
|
||||
text: 'Share',
|
||||
icon: 'share',
|
||||
data: 10,
|
||||
handler: () => {
|
||||
console.log('Share clicked');
|
||||
}
|
||||
}, {
|
||||
text: 'Play (open modal)',
|
||||
icon: 'caret-forward-circle',
|
||||
data: 'Data value',
|
||||
handler: () => {
|
||||
console.log('Play clicked');
|
||||
}
|
||||
@ -187,8 +200,8 @@ async function presentActionSheet() {
|
||||
document.body.appendChild(actionSheet);
|
||||
await actionSheet.present();
|
||||
|
||||
const { role } = await actionSheet.onDidDismiss();
|
||||
console.log('onDidDismiss resolved with role', role);
|
||||
const { role, data } = await actionSheet.onDidDismiss();
|
||||
console.log('onDidDismiss resolved with role and data', role, data);
|
||||
}
|
||||
```
|
||||
|
||||
@ -270,18 +283,23 @@ export const ActionSheetExample: React.FC = () => {
|
||||
role: 'destructive',
|
||||
icon: trash,
|
||||
id: 'delete-button',
|
||||
data: {
|
||||
type: 'delete'
|
||||
},
|
||||
handler: () => {
|
||||
console.log('Delete clicked');
|
||||
}
|
||||
}, {
|
||||
text: 'Share',
|
||||
icon: share,
|
||||
data: 10,
|
||||
handler: () => {
|
||||
console.log('Share clicked');
|
||||
}
|
||||
}, {
|
||||
text: 'Play (open modal)',
|
||||
icon: caretForwardCircle,
|
||||
data: 'Data value',
|
||||
handler: () => {
|
||||
console.log('Play clicked');
|
||||
}
|
||||
@ -328,18 +346,23 @@ export class ActionSheetExample {
|
||||
role: 'destructive',
|
||||
icon: 'trash',
|
||||
id: 'delete-button',
|
||||
data: {
|
||||
type: 'delete'
|
||||
},
|
||||
handler: () => {
|
||||
console.log('Delete clicked');
|
||||
}
|
||||
}, {
|
||||
text: 'Share',
|
||||
icon: 'share',
|
||||
data: 10,
|
||||
handler: () => {
|
||||
console.log('Share clicked');
|
||||
}
|
||||
}, {
|
||||
text: 'Play (open modal)',
|
||||
icon: 'caret-forward-circle',
|
||||
data: 'Data value',
|
||||
handler: () => {
|
||||
console.log('Play clicked');
|
||||
}
|
||||
@ -360,8 +383,8 @@ export class ActionSheetExample {
|
||||
});
|
||||
await actionSheet.present();
|
||||
|
||||
const { role } = await actionSheet.onDidDismiss();
|
||||
console.log('onDidDismiss resolved with role', role);
|
||||
const { role, data } = await actionSheet.onDidDismiss();
|
||||
console.log('onDidDismiss resolved with role and data', role, data);
|
||||
}
|
||||
|
||||
render() {
|
||||
@ -401,6 +424,9 @@ export default defineComponent({
|
||||
role: 'destructive',
|
||||
icon: trash,
|
||||
id: 'delete-button',
|
||||
data: {
|
||||
type: 'delete'
|
||||
},
|
||||
handler: () => {
|
||||
console.log('Delete clicked')
|
||||
},
|
||||
@ -408,6 +434,7 @@ export default defineComponent({
|
||||
{
|
||||
text: 'Share',
|
||||
icon: share,
|
||||
data: 10,
|
||||
handler: () => {
|
||||
console.log('Share clicked')
|
||||
},
|
||||
@ -415,6 +442,7 @@ export default defineComponent({
|
||||
{
|
||||
text: 'Play (open modal)',
|
||||
icon: caretForwardCircle,
|
||||
data: 'Data value',
|
||||
handler: () => {
|
||||
console.log('Play clicked')
|
||||
},
|
||||
@ -438,8 +466,8 @@ export default defineComponent({
|
||||
});
|
||||
await actionSheet.present();
|
||||
|
||||
const { role } = await actionSheet.onDidDismiss();
|
||||
console.log('onDidDismiss resolved with role', role);
|
||||
const { role, data } = await actionSheet.onDidDismiss();
|
||||
console.log('onDidDismiss resolved with role and data', role, data);
|
||||
},
|
||||
},
|
||||
});
|
||||
@ -476,6 +504,9 @@ export default defineComponent({
|
||||
text: 'Delete',
|
||||
role: 'destructive',
|
||||
icon: trash,
|
||||
data: {
|
||||
type: 'delete'
|
||||
}
|
||||
handler: () => {
|
||||
console.log('Delete clicked')
|
||||
},
|
||||
@ -483,6 +514,7 @@ export default defineComponent({
|
||||
{
|
||||
text: 'Share',
|
||||
icon: share,
|
||||
data: 10,
|
||||
handler: () => {
|
||||
console.log('Share clicked')
|
||||
},
|
||||
@ -490,6 +522,7 @@ export default defineComponent({
|
||||
{
|
||||
text: 'Play (open modal)',
|
||||
icon: caretForwardCircle,
|
||||
data: 'Data value',
|
||||
handler: () => {
|
||||
console.log('Play clicked')
|
||||
},
|
||||
@ -525,7 +558,7 @@ export default defineComponent({
|
||||
| ----------------- | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- | ----------- |
|
||||
| `animated` | `animated` | If `true`, the action sheet will animate. | `boolean` | `true` |
|
||||
| `backdropDismiss` | `backdrop-dismiss` | If `true`, the action sheet will be dismissed when the backdrop is clicked. | `boolean` | `true` |
|
||||
| `buttons` | -- | An array of buttons for the action sheet. | `(string \| ActionSheetButton)[]` | `[]` |
|
||||
| `buttons` | -- | An array of buttons for the action sheet. | `(string \| ActionSheetButton<any>)[]` | `[]` |
|
||||
| `cssClass` | `css-class` | Additional classes to apply for custom CSS. If multiple classes are provided they should be separated by spaces. | `string \| string[] \| undefined` | `undefined` |
|
||||
| `enterAnimation` | -- | Animation to use when the action sheet is presented. | `((baseEl: any, opts?: any) => Animation) \| undefined` | `undefined` |
|
||||
| `header` | `header` | Title for the action sheet. | `string \| undefined` | `undefined` |
|
||||
|
||||
@ -7,6 +7,38 @@ const getActiveElementText = async (page) => {
|
||||
return await page.evaluate(el => el && el.textContent, activeElement);
|
||||
}
|
||||
|
||||
test('action-sheet: data', async () => {
|
||||
const page = await newE2EPage({ url: '/src/components/action-sheet/test/basic?ionic:_testing=true' });
|
||||
const didDismiss = await page.spyOnEvent('ionActionSheetDidDismiss');
|
||||
|
||||
await page.click('#buttonData');
|
||||
await page.waitForSelector('#buttonData');
|
||||
|
||||
const actionSheet = await page.find('ion-action-sheet');
|
||||
await actionSheet.waitForVisible();
|
||||
|
||||
const button = await actionSheet.find('button#option');
|
||||
await button.click();
|
||||
|
||||
expect(didDismiss).toHaveReceivedEventDetail({ data: { type: '1' } });
|
||||
});
|
||||
|
||||
test('action-sheet: data cancel', async () => {
|
||||
const page = await newE2EPage({ url: '/src/components/action-sheet/test/basic?ionic:_testing=true' });
|
||||
const didDismiss = await page.spyOnEvent('ionActionSheetDidDismiss');
|
||||
|
||||
await page.click('#buttonData');
|
||||
await page.waitForSelector('#buttonData');
|
||||
|
||||
const actionSheet = await page.find('ion-action-sheet');
|
||||
await actionSheet.waitForVisible();
|
||||
|
||||
const button = await actionSheet.find('button.action-sheet-cancel');
|
||||
await button.click();
|
||||
|
||||
expect(didDismiss).toHaveReceivedEventDetail({ data: { type: 'cancel' }, role: 'cancel' });
|
||||
})
|
||||
|
||||
test('action-sheet: focus trap', async () => {
|
||||
const page = await newE2EPage({ url: '/src/components/action-sheet/test/basic?ionic:_testing=true' });
|
||||
|
||||
|
||||
@ -33,6 +33,7 @@
|
||||
<ion-button expand="block" id="scrollableOptions" onclick="presentScroll()">Scrollable Options</ion-button>
|
||||
<ion-button expand="block" id="scrollWithoutCancel" onclick="presentScrollNoCancel()">Scroll Without Cancel</ion-button>
|
||||
<ion-button expand="block" id="customBackdrop" onclick="presentWithCssClass('custom-backdrop')">Custom Backdrop Opacity</ion-button>
|
||||
<ion-button expand="block" id="buttonData" onclick="presentWithButtonData()">Button data</ion-button>
|
||||
</ion-content>
|
||||
|
||||
</ion-app>
|
||||
@ -427,6 +428,28 @@
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
async function presentWithButtonData() {
|
||||
await openActionSheet({
|
||||
buttons: [
|
||||
{
|
||||
text: 'Option 1',
|
||||
id: 'option',
|
||||
data: {
|
||||
type: '1'
|
||||
}
|
||||
},
|
||||
{
|
||||
text: 'Cancel',
|
||||
role: 'cancel',
|
||||
id: 'cancel',
|
||||
data: {
|
||||
type: 'cancel'
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
|
||||
@ -20,18 +20,23 @@ export class ActionSheetExample {
|
||||
role: 'destructive',
|
||||
icon: 'trash',
|
||||
id: 'delete-button',
|
||||
data: {
|
||||
type: 'delete'
|
||||
},
|
||||
handler: () => {
|
||||
console.log('Delete clicked');
|
||||
}
|
||||
}, {
|
||||
text: 'Share',
|
||||
icon: 'share',
|
||||
data: 10,
|
||||
handler: () => {
|
||||
console.log('Share clicked');
|
||||
}
|
||||
}, {
|
||||
text: 'Play (open modal)',
|
||||
icon: 'caret-forward-circle',
|
||||
data: 'Data value',
|
||||
handler: () => {
|
||||
console.log('Play clicked');
|
||||
}
|
||||
@ -52,8 +57,8 @@ export class ActionSheetExample {
|
||||
});
|
||||
await actionSheet.present();
|
||||
|
||||
const { role } = await actionSheet.onDidDismiss();
|
||||
console.log('onDidDismiss resolved with role', role);
|
||||
const { role, data } = await actionSheet.onDidDismiss();
|
||||
console.log('onDidDismiss resolved with role and data', role, data);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -9,18 +9,23 @@ async function presentActionSheet() {
|
||||
role: 'destructive',
|
||||
icon: 'trash',
|
||||
id: 'delete-button',
|
||||
data: {
|
||||
type: 'delete'
|
||||
},
|
||||
handler: () => {
|
||||
console.log('Delete clicked');
|
||||
}
|
||||
}, {
|
||||
text: 'Share',
|
||||
icon: 'share',
|
||||
data: 10,
|
||||
handler: () => {
|
||||
console.log('Share clicked');
|
||||
}
|
||||
}, {
|
||||
text: 'Play (open modal)',
|
||||
icon: 'caret-forward-circle',
|
||||
data: 'Data value',
|
||||
handler: () => {
|
||||
console.log('Play clicked');
|
||||
}
|
||||
@ -41,7 +46,7 @@ async function presentActionSheet() {
|
||||
document.body.appendChild(actionSheet);
|
||||
await actionSheet.present();
|
||||
|
||||
const { role } = await actionSheet.onDidDismiss();
|
||||
console.log('onDidDismiss resolved with role', role);
|
||||
const { role, data } = await actionSheet.onDidDismiss();
|
||||
console.log('onDidDismiss resolved with role and data', role, data);
|
||||
}
|
||||
```
|
||||
|
||||
@ -73,18 +73,23 @@ export const ActionSheetExample: React.FC = () => {
|
||||
role: 'destructive',
|
||||
icon: trash,
|
||||
id: 'delete-button',
|
||||
data: {
|
||||
type: 'delete'
|
||||
},
|
||||
handler: () => {
|
||||
console.log('Delete clicked');
|
||||
}
|
||||
}, {
|
||||
text: 'Share',
|
||||
icon: share,
|
||||
data: 10,
|
||||
handler: () => {
|
||||
console.log('Share clicked');
|
||||
}
|
||||
}, {
|
||||
text: 'Play (open modal)',
|
||||
icon: caretForwardCircle,
|
||||
data: 'Data value',
|
||||
handler: () => {
|
||||
console.log('Play clicked');
|
||||
}
|
||||
|
||||
@ -17,18 +17,23 @@ export class ActionSheetExample {
|
||||
role: 'destructive',
|
||||
icon: 'trash',
|
||||
id: 'delete-button',
|
||||
data: {
|
||||
type: 'delete'
|
||||
},
|
||||
handler: () => {
|
||||
console.log('Delete clicked');
|
||||
}
|
||||
}, {
|
||||
text: 'Share',
|
||||
icon: 'share',
|
||||
data: 10,
|
||||
handler: () => {
|
||||
console.log('Share clicked');
|
||||
}
|
||||
}, {
|
||||
text: 'Play (open modal)',
|
||||
icon: 'caret-forward-circle',
|
||||
data: 'Data value',
|
||||
handler: () => {
|
||||
console.log('Play clicked');
|
||||
}
|
||||
@ -49,8 +54,8 @@ export class ActionSheetExample {
|
||||
});
|
||||
await actionSheet.present();
|
||||
|
||||
const { role } = await actionSheet.onDidDismiss();
|
||||
console.log('onDidDismiss resolved with role', role);
|
||||
const { role, data } = await actionSheet.onDidDismiss();
|
||||
console.log('onDidDismiss resolved with role and data', role, data);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@ -22,6 +22,9 @@ export default defineComponent({
|
||||
role: 'destructive',
|
||||
icon: trash,
|
||||
id: 'delete-button',
|
||||
data: {
|
||||
type: 'delete'
|
||||
},
|
||||
handler: () => {
|
||||
console.log('Delete clicked')
|
||||
},
|
||||
@ -29,6 +32,7 @@ export default defineComponent({
|
||||
{
|
||||
text: 'Share',
|
||||
icon: share,
|
||||
data: 10,
|
||||
handler: () => {
|
||||
console.log('Share clicked')
|
||||
},
|
||||
@ -36,6 +40,7 @@ export default defineComponent({
|
||||
{
|
||||
text: 'Play (open modal)',
|
||||
icon: caretForwardCircle,
|
||||
data: 'Data value',
|
||||
handler: () => {
|
||||
console.log('Play clicked')
|
||||
},
|
||||
@ -59,8 +64,8 @@ export default defineComponent({
|
||||
});
|
||||
await actionSheet.present();
|
||||
|
||||
const { role } = await actionSheet.onDidDismiss();
|
||||
console.log('onDidDismiss resolved with role', role);
|
||||
const { role, data } = await actionSheet.onDidDismiss();
|
||||
console.log('onDidDismiss resolved with role and data', role, data);
|
||||
},
|
||||
},
|
||||
});
|
||||
@ -97,6 +102,9 @@ export default defineComponent({
|
||||
text: 'Delete',
|
||||
role: 'destructive',
|
||||
icon: trash,
|
||||
data: {
|
||||
type: 'delete'
|
||||
}
|
||||
handler: () => {
|
||||
console.log('Delete clicked')
|
||||
},
|
||||
@ -104,6 +112,7 @@ export default defineComponent({
|
||||
{
|
||||
text: 'Share',
|
||||
icon: share,
|
||||
data: 10,
|
||||
handler: () => {
|
||||
console.log('Share clicked')
|
||||
},
|
||||
@ -111,6 +120,7 @@ export default defineComponent({
|
||||
{
|
||||
text: 'Play (open modal)',
|
||||
icon: caretForwardCircle,
|
||||
data: 'Data value',
|
||||
handler: () => {
|
||||
console.log('Play clicked')
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user