Dynamic action sheet buttons - every handler method is the same(the last one)

Some time ago i created an ionic3/angular4 app and now i was playing around with the action sheet component.

When i create the buttons directly(as in the code samples described) everthing woks as expected:

buttons: [
        {
          text: 'Delete',
          role: 'destructive',
          icon: !this.platform.is('ios') ? 'trash' : null,
          handler: () => {
            console.log('Delete clicked');
          }
        },
        {
          text: 'Share',
          icon: !this.platform.is('ios') ? 'share' : null,
          handler: () => {
            console.log('Share clicked');
          }
        },
        {
          text: 'Play',
          icon: !this.platform.is('ios') ? 'arrow-dropright-circle' : null,
          handler: () => {
            console.log('Play clicked');
          }
        },
        {
          text: 'Favorite',
          icon: !this.platform.is('ios') ? 'heart-outline' : null,
          handler: () => {
            console.log('Favorite clicked');
          }
        },
        {
          text: 'Cancel',
          role: 'cancel', // will always sort to be on the bottom
          icon: !this.platform.is('ios') ? 'close' : null,
          handler: () => {
            console.log('Cancel clicked');
          }
        }
      ]

Clicking the buttons shows the correct log message.

But when i create the buttons dynamically like this one:

buttons: this.createButtons(),

and the method looks like the following:

  createButtons() {
    let buttons = [];
    for (var index in this.possibleButtons) {
      let button = {
        text: this.possibleButtons[index].text,
        icon: this.possibleButtons[index].icon,
        handler: () => {
          console.log('setting icon ' + this.possibleButtons[index].icon);
          return true;
        }
      }
      buttons.push(button);
    }
    return buttons;
  }

The buttons are still created correctly(text and icon), but when i click one of them. It calls everytime the same handler method.(the last one)
So the log message is always “setting icon close”

Here’s the full .ts code:

import { Component } from '@angular/core';

import { Platform, ActionSheetController } from 'ionic-angular';


@Component({
  templateUrl: 'actionsheet.html',
  selector: 'page-actionsheet'
})
export class ActionsheetPage {
headerText: string;
possibleButtons = [{ icon: 'trash', text: 'Trash Collector' }, { icon: 'arrow-dropright-circle', text: 'Networker' }, { icon: 'share', text: 'Player' }, { icon: 'heart-outline', text: 'Harmonizer' }, { icon: 'close', text: 'Canceller' }];

  constructor(
    public platform: Platform,
    public actionsheetCtrl: ActionSheetController
  ) {
    this.headerText = "Action sheet";
  }

  openMenu() {
    let actionSheet = this.actionsheetCtrl.create({
      title: 'Albums',
      cssClass: 'action-sheets-basic-page',
      buttons: this.createButtons()
      // buttons: [
      //   {
      //     text: 'Delete',
      //     role: 'destructive',
      //     icon: !this.platform.is('ios') ? 'trash' : null,
      //     handler: () => {
      //       console.log('Delete clicked');
      //     }
      //   },
      //   {
      //     text: 'Share',
      //     icon: !this.platform.is('ios') ? 'share' : null,
      //     handler: () => {
      //       console.log('Share clicked');
      //     }
      //   },
      //   {
      //     text: 'Play',
      //     icon: !this.platform.is('ios') ? 'arrow-dropright-circle' : null,
      //     handler: () => {
      //       console.log('Play clicked');
      //     }
      //   },
      //   {
      //     text: 'Favorite',
      //     icon: !this.platform.is('ios') ? 'heart-outline' : null,
      //     handler: () => {
      //       console.log('Favorite clicked');
      //     }
      //   },
      //   {
      //     text: 'Cancel',
      //     role: 'cancel', // will always sort to be on the bottom
      //     icon: !this.platform.is('ios') ? 'close' : null,
      //     handler: () => {
      //       console.log('Cancel clicked');
      //     }
      //   }
      // ]
    });
    actionSheet.present();
  }

  createButtons() {
    let buttons = [];
    for (var index in this.possibleButtons) {
      let button = {
        text: this.possibleButtons[index].text,
        icon: this.possibleButtons[index].icon,
        handler: () => {
          console.log('setting icon ' + this.possibleButtons[index].icon);
          return true;
        }
      }
      buttons.push(button);
    }
    return buttons;
  }
}

Any idea what i’m doing wrong here?
Thanks in advance!

3 Likes

If possible, provide the full .ts code.

added the full code to the topic.

Never use var. JavaScript is a very poorly designed language. let works like a sane person would expect var to, and var works like a nutjob on a 72-hour Red Bull bender thought was a good idea. See here for more background, especially the “cleaner code in inner functions” bit.

2 Likes

As @rapropos suggested, if you change the var to let it’ll start working. I do not personally like the for .. in here though, a for .. of is better suited. Something like this:

for (let btn of this.possibleButtons) {
  let button = {
    text: btn.text,
    icon: btn.icon,
    ....
  }
  buttons.push(button);
}
3 Likes

Thanks for helping and your suggestions!
Learned a lot from you guys :slight_smile:

1 Like

thank you very very very much,
i just replaced “var” with “let” and it is fixed like a charm

this solution works for me!! :slight_smile:

Tnks!!

My handlers not work,
Whichever button I click it always takes the last handle ()

has anyone solved this? getting same issue.

 async DownloadItems(){ 
    let opts = {
      header: "Select Download Options",
      buttons: this.createDownlodOptionsButtons(),
    };
    const actionSheet = await this.actionSheetCtrl.create(opts);
    await actionSheet.present();
  }

  createDownlodOptionsButtons(){
    let buttons = [];
    let options = [
        { name:"List 1", id:"b"},
        { name:"List 2", id:"a"},
        { name:"List 3, id:"c"},
        { name:"List 4, id:"d"},
    ];

    for (var i = 0; i < options.length; i++) {
      let opt = options[i];
      let button = {
        text: opt.name, 
        handler: async () => {
          
      };
      buttons.push(button);
    }
    return buttons;
  }