Pass data into Ionic ActionSheet

Is there any way to send that into the handler on the Ionic 2 ActionSheet?

I am population an ActionSheet dynamically and I need to send an index or something to know which button am I clicking.

Any thoughts?

Cheers.

Anyone? I have been struggling with this.

So you could pass data along how you normally would.

constructor(nav: NavController) {
  this.nav = nav;
  this.buttons = //what ever you needed to generate buttons
}

presentActionSheet() {
  let actionSheet = ActionSheet.create({
    title: 'Modify your album',
    buttons: this.buttons // follows the object model of an array of buttons
  this.nav.present(actionSheet);
}
1 Like

Sorry, I might not have explained it properly:

for(var  i = 0; i < anyarray; i++){
    var button= {
        text: 'button name',
        handler: () => {
             //Get which button was clicked
        }
     }
    actionSheet.addButton(button);
}

(sorry about the identation, didn’t manage to make it proper)

How can I get which button was clicked on the handler? I want to get an index or anything that allows me to identify which button is being clicked.

Thanks

Hmm, I’d think you’d be able to pass i along in there, right?

for(var  i = 0; i < anyarray; i++){
    var button= {
        text: 'button name',
        handler: (i) => {
             //Get which button was clicked
             console.log(i)
        }
     }
    actionSheet.addButton(button);
}
1 Like

No, that is my issue. I get undefined when trying to access i. Probably because the handler is only called when the button is clicked so i is already gone by that time. I did not find any way to access the button data. On Ionic 1 there was a way to do it.

Also, if I don’t pass i to the handler and try to access it inside the handler, I get the value of the length of the array as the loop will be done when the handler is called.

Hmm, now it’s not perfect, but this is pretty close to what you would want.

export class HomePage {
  constructor(public nav: NavController) {

    this.actionSheet = ActionSheet.create({
      title: 'Modify your album'
    });
    for (let i = 0; i < 5; i++) {
      var button = {
        text: 'button' + i,
        handler: () => {
          console.log(i)
        }
      }
      this.actionSheet.addButton(button)
    }
  }

  presentActionSheet() {
    this.nav.present(this.actionSheet);
  }
}

2 Likes

I tried your code but I only get 5 as the output for all the buttons.

Am I missing something?

“i” will always be the last number in the loop since the handler is not called synchronously…I think the way you are using action sheet should be adjusted slightly. Instead of passing data like that, why not set the handler dynamically to a certain function for each button.

Example

presentActionSheet() {
        let actionSheet = ActionSheet.create({
            title: ' Actions',

        });

        function func1() {

        }

        function func2() {

        }

        let buttonArray = [{
            text: 'Btn 1',
            handler: func1
        },
            {
                text: 'Btn 2',
                handler: func2
            }];

        for (let i = 0; i < buttonArray.length; i++) {
            actionSheet.addButton({
                text: buttonArray[i].text,
                handler: buttonArray[i].handler
            })
        }

        this.nav.present(actionSheet);
    }

Apologies for interrupting the conversation.

Additionally, if you would like to stick with the data passing approach, you could always go with the modal or alerts as they have the triggers to pass data to and from easily.

Hey keczan,

Thank you for your reply. In my case I cannot use your example as I do not know exactly how many buttons I will have. I know that there will be max 3 but I do not want to use your approach as it would be an ugly workaround for my situation. The idea is similar to gmail`s switch account or any app that you can switch between two accounts.

It fits our design to have it in the ActionSheet. Any other suggestions?

Are you certain that you used mhartington’s code exactly? Although it might seem like a trivial thing, he’s got let defining the loop variable where you had var, and that makes all the difference in avoiding a common pitfall with JavaScript scoping.

my only thought at this point is to extend the action class and override the click function. You can pass through custom data to the button structures as keys. This is where i would start.

ActionSheet class click handler

click(button, dismissDelay?) {
    let shouldDismiss = true;

    if (button.handler) {

      if (button.handler() === false) { ///Adjust this line.....button.handler(data)

        shouldDismiss = false;
      }
    }

    if (shouldDismiss) {
      setTimeout(() => {
        this.dismiss(button.role);
      }, dismissDelay || this._config.get('pageTransitionDelay'));
    }
  }

pass custom properties

actionSheet.addButton({text:'test', customProp:'prop', handler:(data) => {

})
1 Like

Yes, I copied the code exactly as mhartington posted. Still I had the incorrect output.

I was hoping for something that was already implemented, similar to what is done in Ionic 1. Thanks for your reply, I’ll probably go that way.

I tried it in a scratch project, and it worked as advertised with numbers 0 through 4, both with the text inside the buttons and the log in the console.

Might be something with my project. I’ll try again on an scratch project. Thanks for the tip!

When I tested on my project it works for the buttons text but not for the console log. Also, declaring the ActionSheet on the constructor instead of inside the presentActionSheet() method, makes the ActionSheet only clickable once. It might be an issue with my ActionSheet class being a Component and it is being imported on every page.

I think I also saw this behavior, FWIW.

Did you find a way to do what you want?

In my case i am displaying action sheet on image long press to delete, how can i get index of that image in handler?
or should i try other way or component to achieve this?

You could do something like this

actionSheet.addButton({
text: title,
handler: () => {
this.function(anyArg);
}});

I think the only thing you can do, to pass the index in the handler is

for (var i = 0; i < array.length; i++){
	actionSheet.addButton({
		text: title,
		handler: this.myFunction.bind(this, i)
	})
}

myFunction(i){
do something ...
}

1 Like