2

I have a nav menu that is rendered using a navigation.ts json file for the menu items. When it gets to the navitem component it uses a ngIf to check if the item from the navigation file has a "function" key and if it does, the desired behavior is for it to use the string value from item.function in the object to fill the value for the (click) event.

In reality, the console throws an error saying "_co.item.function is not a function"

HTML

<span class="nav-link" *ngIf="item.function" (click)="item.function()" matRipple>
    <mat-icon class="nav-link-icon" *ngIf="item.icon">{{item.icon}}</mat-icon>
    <span class="nav-link-title" [translate]="item.translate">{{item.title}}</span>
    <span class="nav-link-badge" *ngIf="item.badge" [translate]="item.badge.translate"
        [ngStyle]="{'background-color': item.badge.bg,'color': item.badge.fg}">
    {{item.badge.title}}
    </span>
</span>

Navigation.ts

      [{
"id": "accounting",
"title": "Accounting",
"type": "collapse",
"children": [
  {
    "id" : "salesmenSalesLocation",
    "title": "Salesmen Sales Location",
    "type": "item",
    "function": "handleSelect(ReportTypes.SalesmenSalesLocations)"
  },
  {
    "id": "laggingLedgerEntries",
    "title": "Lagging Ledger Entries",
    "type": "item",
    "function": "handleSelect(ReportTypes.LaggingLedgerEntries)"
  }
 ]}]

I have also tried it as (click)="item.function" with no success.

2
  • 3
    it might be an actual function but as far as your item.function object is concerned, it is just a string and hence not a function Commented Sep 24, 2018 at 20:06
  • 1
    Where is the data coming from? Do you have any control over the source? There's really no safe way to parse this as it is. Commented Sep 24, 2018 at 20:09

3 Answers 3

4

I'm assuming you can change the data source here, because otherwise I don't see any good solution.

A string is not a function, and while you can turn it into one with eval that is a bad idea. What you should really do instead is just pass in a value that tells the function what to use.

Change your data to something like this:

{
  "id" : "salesmenSalesLocation",
  "title": "Salesmen Sales Location",
  "type": "item",
  "reportTypeSource": "SalesmenSalesLocations"
},
{
  "id": "laggingLedgerEntries",
  "title": "Lagging Ledger Entries",
  "type": "item",
  "reportTypeSource": "LaggingLedgerEntries"
}

Then pass that value to your function and use that to tell it where to look:

handleSelect (reportTypeSource: string) {
    const reportType = ReportTypes[reportTypeSource]
    // continue as before
}

And call it in your HTML like this:

(click)="handleSelect(item.reportTypeSource)"
Sign up to request clarification or add additional context in comments.

Comments

3

Problem lies here:

"function": "handleSelect(ReportTypes.LaggingLedgerEntries)"

And here:

(click)="item.function()"

You cannot simply pass a string and expect the component to execute a function and also know exactly what to do. Here you need to pass the actual function.

Your setup looks over-config'd. I would tear the config down and put the logic into the component itself. Don't be afraid to have more template as well, if anything it makes things more legible (as opposed to the config)

Comments

2

Does that function exist in the component or just the model? If it is just on the model it won't work. (click) is looking for a method on the component. It is, ostensibly just a string in this instance.

2 Comments

Yes, there is a function handleSelect(reportType: number)
On the component? right now you are passing a string, pass the actual function name.

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.