简体   繁体   中英

Node / Pug / Jade Interpolate into variable

I've got a whole bunch of data being passed to a view in a Node App, and a bunch of it relates to budgets, specifically quote vs. actual.

The variables are all named similarly, like this

s_budget_quote_labour = 500
s_budget_actual_labour = 400
s_budget_quote_food = 1000
s_budget_actual_food= 1100

I want to create a custom array in my Pug template, that consists of all the cost "types" and then iterate over them, piping the cost type into the variable name. Basically something like this:

    - expenseArray = ['Food', 'Labor']
    - each expense, i in expenseArray
      - var expense_budget = 'info.s_budget_' + expense  
      - var expense_actual = 'info.s_actual_' + expense  
      tr
        td ${expense}
        td ${expense_budget}
        td ${expense_actual}

The idea being that it will loop over all of the items in my array, and pull together the proper html to build my table of expenses. I've tried piping it directly into the td a couple different ways too, but no luck. Samples...

td #{info.s_actual_${expense}}
td !{info.s_actual_${expense}}

And a few other variants... all without luck. Any idea if this is possible and how to do it?

eval should let you get variables with dynamic names. And you can use .toLowerCase to make the case match:

- expenseArray = ['Food', 'Labor']
- each expense, i in expenseArray
  - var expense_budget = eval('info.s_budget_' + expense.toLowerCase())
  - var expense_actual = eval('info.s_actual_' + expense.toLowerCase())
  tr
    td ${expense}
    td ${expense_budget}
    td ${expense_actual}

However, eval could cause security problems if users can specify the value of expenseArray . Those users could cause arbitrary JavaScript to be run for anyone who visits that page. This solution would also need more code if you needed it to support spaces or special characters in the names of expense types. So I don't recommend this.

Instead, you should change the format of the info variable that is sent to your view. Make it so an object or Map is sent instead of multiple variables with a special naming scheme. For example, info could be this:

var info = {
  'Labour': {quote: 500, actual: 400},
  'Food': {quote: 1000, actual: 1100},
}

And then your template would be this:

- expenseArray = ['Food', 'Labor']
- each expense, i in expenseArray
  - var expense_budget = info[expense].quote
  - var expense_actual = info[expense].actual
  tr
    td ${expense}
    td ${expense_budget}
    td ${expense_actual}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM