0

I would like to set different methods to be called at the (click) event. I created an array of dictionaries in the ts-File:

headerElements = [
{
  descriptor: "Name",
  icon: "/assets/imgs/name-32.png",
  cursor: "default",
  event: "null"
},
{
  descriptor: "Price",
  icon: "/assets/imgs/description-32.png",
  cursor: "pointer",
  event: "orderByPrice()"
},
{
  descriptor: "Link",
  icon: "/assets/imgs/timer-32.png",
  cursor: "default",
  event: "null"
},
{
  descriptor: "Datum",
  icon: "/assets/imgs/timer-32.png",
  cursor: "pointer",
  event: "null"
}
];

The orderByPrice-Method looks like this:

  orderByPrice() {
    this.isSortedAsc = !this.isSortedAsc;
    const direction = this.isSortedAsc ? "desc" : "asc";
    this.gearPieces = this.gearService.getGearComponentsOrderByPrice(direction);
  }

I call it like this in the html-File:

<table class="table table-dark">
  <thead>
    <tr>
      <th *ngFor="let header of headerElements">
        <img src={{header.icon}} width="32" height="32" style="cursor: {{header.cursor}};" (click)="{{header.event}}"/>{{header.descriptor}}
      </th>
    </tr>
  </thead>
</table>

Unfortunately, setting a specific method to be called on (click) gives me this error:

Template parse errors: Parser Error: Got interpolation ({{}}) where expression was expected at column 0 in [{{header.event}}]

Is it even possible, to accomplish this?

0

2 Answers 2

1

One of the easy solution will be (If headerElements variable data is not retrieved from server and is locally defined):

Change headerElements.event as follows:

headerElements = [
{
  descriptor: "Name",
  icon: "/assets/imgs/name-32.png",
  cursor: "default",
  event: () => {return this.test1();}
},
{
  descriptor: "Price",
  icon: "/assets/imgs/description-32.png",
  cursor: "pointer",
  event: () => {return null;}
},
{
  descriptor: "Link",
  icon: "/assets/imgs/timer-32.png",
  cursor: "default",
  event: () => {return null;}
},
{
  descriptor: "Datum",
  icon: "/assets/imgs/timer-32.png",
  cursor: "pointer",
  event: () => {return this.test2('It works!');}
}
];

Also, modify HTML click event as follows:

(click)='value.event()'
Sign up to request clarification or add additional context in comments.

Comments

0

Update

Instead of function names, you can directly attach the function references to the event prop in your object. So if you have a method:

orderByPrice() {
    console.log("order by price called");
}

attach the references like:

headerElements = [
  {
    descriptor: "Price",
    icon: "/assets/imgs/description-32.png",
    cursor: "pointer",
    event: this.orderByPrice //<---- assign the actual reference of the function
   },
   .
   .
]

Old answer (I don't know what was I thinking)

You can create reference for the methods in your class. Something like:

orderByPrice = () => {
    console.log("order by price called");
}

Use the function references for assigning to event to header elements instead of their names

The create your object like:

headerElements = [
  {
    descriptor: "Name",
    icon: "/assets/imgs/name-32.png",
    cursor: "default",
    event: null
  },
  {
    descriptor: "Price",
    icon: "/assets/imgs/description-32.png",
    cursor: "pointer",
    event: this.orderByPrice //<---- assign the actual reference of the function
  },
  {
    descriptor: "Link",
    icon: "/assets/imgs/timer-32.png",
    cursor: "default",
    event: null // <-- as described in comments have it falsy, actual null
  },
  {
    descriptor: "Datum",
    icon: "/assets/imgs/timer-32.png",
    cursor: "pointer",
    event: null
  }
];

Have your HTML like:

  <th *ngFor="let header of headerElements">
    <img src={{header.icon}} width="32" height="32" style="cursor: {{header.cursor}};" (click)="header.event && header.event()"/>{{header.descriptor}}
  </th>

Edit

(Based on the comments)

This part contains checks and explanations if it is correct to have a variable in an angular class referencing a function.

I checked the component instance when we add a variable as a function reference rather than adding a named function in the class.

So, When a named function is added it appears in the prototype of the component instance. But if I have a variable reference to the function then the variable(so the function) appears directly in the component instance(this means code duplication).

To avoid this, we can add the function to the prototype of the class.

  AppComponent.prototype['orderByPrice'] = (): void => {
    console.log("order by price called");
  }

I couldn't find any other differences. I am open to suggestions, counter questions and correcting my mistake if this is not correct.

Thanks!

9 Comments

header.event evaluates to true since it's string
And btw it's not correct because that's not how Angular methods are defined
@CristianTraìna: Right! let me rectify thtis.
I also add that if he/she receives the object from the server, he can map strings to functions explictly, maybe with a switch-case
And, the last thing, is that you can use the elvy operator header?.event(). I had written my own answer but since you were faster I deleted it, so let's integrate :)
|

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.