ionic-team / ionic-framework

A powerful cross-platform UI toolkit for building native-quality iOS, Android, and Progressive Web Apps with HTML, CSS, and JavaScript.
https://ionicframework.com
MIT License
50.93k stars 13.52k forks source link

feat: dismiss data in overlay button handler return #26013

Open Spinnenzunge opened 1 year ago

Spinnenzunge commented 1 year ago

Prerequisites

Describe the Feature Request

It would be great if the handler function of an overlay button (e.g. IonActionSheetButton) would allow overlay data as a return value.

Describe the Use Case

I have an IonActionSheet with three buttons that resolve some data from a promise. When the data is resolved and is not null, the IonActionSheet should dismiss with given data in the OverlayEventDetail. If the data is null, I do not want to close the ActionSheet by returning false in the handler method.

At the moment I can not return data inside the handler value except by using the dismiss method of the created action sheet itself.

Describe Preferred Solution

The handler() method on an IonActionSheetButton should accept OverlayEventDetail object as return value

public async browseFile(): Promise<SandboxFile | null> {
  const actionSheet = await this.actionSheetController.create({
    buttons: [
      {
        text: 'Scan Document',
        role: 'scanner',
        handler: async () => {
          const file = await this.browseScanner();
          return file ? {file} : false;
        }
      },
      {
        text: 'Cancel',
        role: 'cancel'
      }
    ]
  });
  await actionSheet.present();
  const {data, role} = await actionSheet.onWillDismiss<{file: SandboxFile}>();
  return data?.file || null;
}

Describe Alternatives

No response

Related Code

At the moment I have to solve the problem with using the dismiss() method of the action sheet element. But this results in the buttons role attribute being ignored because the dismiss is triggered by the dismiss() method and not via the handler default.

public async browseFile(): Promise<SandboxFile | null> {
  const actionSheet = await this.actionSheetController.create({
    buttons: [
      {
        text: 'Scan Document',
        role: 'scanner',
        handler: async () => {
          const file = await this.browseScanner();
          if (!file) {
            // if file is null or undefined, I do not want to close the action sheet
            return false;
          }
          // dismissing in handler needs to be done with via the action sheet object
          await actionSheet.dismiss({file});
        }
      },
      {
        text: 'Camera',
        role: 'camera',
        handler: async () => {
          const file = await this.browseCamera();
          if (!file) {
            return false;
          }
          await actionSheet.dismiss({file});
        }
      },
      {
        text: 'Cancel',
        role: 'cancel'
      }
    ]
  });
  await actionSheet.present();
  const {data, role} = await actionSheet.onWillDismiss<{file: SandboxFile}>();
  return data?.file || null;
}

Additional Information

No response

liamdebeasi commented 1 year ago

Thanks for the report. The ActionSheetButton interface has a data property that you can use to return data from the handler. Have you tried using that? We have a work in progress component playground that shows how to use this: https://ionic-docs-git-fw-1309-ionic1.vercel.app/docs/api/action-sheet

Spinnenzunge commented 1 year ago

Hi @liamdebeasi yes I have seen that property, but this is just a static property value of a button element that gets passed trough to the dismiss event.

My use case is processing business logic inside the handler function (maybe async and impure with DI, etc.) as shown in my example. For that I cannot really use a static data attribute but need to be able to return it in the button handler.