6

I am having a little trouble with binding a dynamic function to a click event. Please see below:-

File 1

<title-bar [actions]='[{title: "Create A New Plan", link: "hello"}]' ></title-bar>

File 2

<div class="actions" *ngIf="actions">
    <a *ngFor="let action of actions" class="ui primary button" (click)="[action.link]()">{{action.title}}</a>
</div>

All of the code is working perfectly apart from when I am binding the action.link in the (click).

If I create the following button:-

<button (click)="hello()"></button>

It calls the hello() function as it should. but for some reason I am not able to get this to work dynamically.

Does anybody have a simple solution to this I may have over looked?

The function is calling a simple alert just for testing:-

public hello() {
    alert('test');
}

II have attempted to change the click event to the following but with no joy:-

(click)="action.link"
(click)="[action.link]()"
(click)="this[action.link]()"

I get the following errors respectively:-

No error, but not function called
inline template:3:2 caused by: ["hello"] is not a function
inline template:3:2 caused by: self.parentView.parentView.context[self.context.$implicit.link] is not a function

Any help with a push in the right direction will be very much appreciated.

0

4 Answers 4

13

In the component you need

get self() { return this; }

and in the template

<a *ngFor="let action of actions" class="ui primary button"
  (click)="self[action.link]()">{{action.title}}</a>

Use

<a *ngFor="let action of actions" class="ui primary button"
  (click)="this[action.link]()">{{action.title}}</a>
Sign up to request clarification or add additional context in comments.

9 Comments

Would you be able to explain and elaborate on the "get self() { return this; }" function?
With (click)="[action.link]()" you create an array with one item action.link and apply a function call (which is not expected to work). With (click)="self[action.link]()" you reference the property with the name from action.link of the object returned by self which is the components class instance (which I assumed is what you want). this is not supported in the template AFAIK, so self is a workaround to make this available.
Thank you for explaining, this work around works perfectly.
this is now available in the template to refer to the component class, so the self getter is no longer required
I just went back to your self example above and it now works in 9. I guess sometimes we have to go back a little to move forward? ;-)
|
4

I needed to do something similar with ngFor. Accepted answer works but gave me a linting error: 'Call target is not callable'

There's another SO answer from Günter which helped me find a lint-error free solution : Angular2 passing function as component input is not working

My component.ts

this.myLinks = [
  {
    imgSrc: 'assets/a.png,
    clickFunction: this.aFn,
  },
  {
    imgSrc: 'assets/b.png,
    clickFunction: this.bFn,
  },
];


aFn() {
  console.log('function A');
}
bFn() {
  console.log('function B');
}

My template.html

<div *ngFor="let link of myLinks">
   <img
     [src]="link.imgSrc"
     (click)="link.clickFunction.apply(this)"
   />
</div>

Comments

0

It worked for me like this:

(click)=self[action.link]()

Comments

0

Component.ts

items = [
  {
    name: 'share',
    action: this.share
  },
  {
    name: 'report',
    action: this.report
  }
];

share() {}
report() {}

Component.html

<el *ngFor="let i of items" (click)="i.action()"></el>

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.