andthereitgoes
andthereitgoes

Reputation: 889

Passing function as JSON data in angular 2 typescript

I am using angular 2.0.0 with Typescript and trying to build a dynamic menu system which works based on JSON array the component receives.

var menu = [
{id:"menu1", title: " Menu 1", action: "addUser()"},
{id:"menu2", title: " Menu 2", action: "addPhoto()"},
{id:"menu3", title: " Menu 3", action: "addEmail()"}
]

I would like to know the following

Thanks for the help.

Upvotes: 4

Views: 2728

Answers (2)

Logan H
Logan H

Reputation: 3423

To bind to the click event dynamically, you do (click)="" Please see Event Binding, but since those are technically strings it won't call a function you need a helper function to determine what function you want to call then it calls the function for you

Plunker Demo

This should work, and the way you have action is fine

@Component({
  selector: 'my-app',
  template: `
      <div class="link" [id]="item.id" *ngFor="let item of menu"
        (click)="callFunction(item.action)">
          {{ item.title }}
      </div>
  `,
})
export class App {
  menu: any;
  constructor() {
    this.menu = [
      {id:"menu1", title: "Add User", action: "addUser()"},
      {id:"menu2", title: "Add Photo", action: "addPhoto()"},
      {id:"menu3", title: "Add Email", action: "addEmail()"}
    ]
  }

  callFunction(func) {
    switch(func) {
      case "addUser()": 
        this.addUser()
        break;
      case "addPhoto()": 
        this.addPhoto()
        break;
      case "addEmail()": 
        this.addEmail()
        break;
      default:
        alert("Not found")
    }
  }

  addUser() {
    alert("Add User Called!");
  }
  addPhoto() {
    alert("Add Photo Called!");
  }
  addEmail() {
    alert("Add Email Called!");
  }
}



For more information on the Template Syntax

Upvotes: 2

angularconsulting.au
angularconsulting.au

Reputation: 28259

(click)="item.action" won't work.

You should do something like that insteard:

(click)="onClick(item)"

Then handle the logic based on item.action value inside your

     onClick(item) { 
          switch (item.action){
            case 'addUser()' :
              this.addUser()
              break;
            case 'addPhoto()' :
              this.addPhoto()
              break;
            default : whatever();
          }
     }

Or antother option is:

Change your menu to by taknig out the () from your actions:

  var menu = [
    {id:"menu1", title: " Menu 1", action: "addUser"},
    {id:"menu2", title: " Menu 2", action: "addPhoto"},
    {id:"menu3", title: " Menu 3", action: "addEmail"}
  ]

Than in your template just do: (click)="item.action ? this[item.action].call(this) : 'return false;'"

Or just: (click)="this[item.action].call(this)" incase if your item.action is compulsory

Upvotes: 3

Related Questions