4

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

  • how to set the click action on the menu dynamically?
  • Do I use Renderer with ElementRef or do I use DynamicComponentLoader?
  • How do I represent the 'action' click function as part of the JSON array above?

Thanks for the help.

2 Answers 2

3

(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

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks. I like how you've given me a few different options. I like the last option best, which seems a bit elegant. Is this a standard way to do something like this dynamically?
@andthereitgoes I am doing second option which is using .call(this) in my current project. This one is much cleaner then the other one which requires you to build additional switch statement.
I am inclined to agree. i have selected that as the answer for now unless some other option or way comes to light - in which case I will update. Thanks!
2

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

1 Comment

Thanks for this method. Is this a standard way to do something like this dynamically?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.