snowleopard
snowleopard

Reputation: 833

How to get javascript variable to be interpreted as attribute in underscore templates

Lets say I have a the following attributes being passed in to an underscore template: name and animaltype. I also have an attribute that varies based on the animaltype. So for example, if animaltype is CAT, then the attribute is called cat_id. If is the animaltype is DOG, then the attribute is dog_id and so on.

I create an input box for each of the animaltype ids but only the box that has an id of the corresponding animaltype should be populated(mapped in via attributes). This ID input box is the one I cannot get to map to the attribute value because I am using javascript to create the name of the attribute is should be expecting. Therefore the actual javascript variable name is being inserted instead of the corresponding resolved attribute value that matches the javascript variable name.

Here is the fiddle http://jsfiddle.net/leopardy/fev4vqmg/1/

What I should get is
Name: Fluffy
Type: CAT
CAT ID: 005
DOG ID:
BIRD ID:

What I really get is
Name: Fluffy
Type: CAT
CAT ID: cat_id
DOG ID:
BIRD ID:
where the cat_id attribute did not resolve in the template.

As a side note, in my real code I am hiding the other ID input boxes that don't correspond to the animal type but for the sake of keeping things simpler, I didn't including the hiding/showing.

Upvotes: 3

Views: 943

Answers (2)

mu is too short
mu is too short

Reputation: 434665

You have the common "I have a variable name in another variable" problem and the solution is the same as it always is: put the things you need to look up by name in a lookup table (i.e. an object in JavaScript).

In your case, I would not _.extend(attributes, {animalTypes:animalTypes}); to mash everything into one pile, I would leave attributes and animalTypes separate so that your _.template call would look like this:

var tmpl = _.template(template);
var html = tmpl({
    animalTypes: animalTypes,
    attributes: attributes
});

Now you can say things like attributes['cat_id'] in your template. Of course, you'll have to refer to everything through animalTypes or attributes but that's pretty minor. Your template would look something like this:

<table>
    <tbody>
            <tr>
                <td>Name:</td>
                <td>
                    <input name="name" type="text" value="<%= attributes.name %>"/>
                </td>
            </tr>
            <tr>
                <td>Type:</td>
                <td>
                    <input name="animal_type" type="text" value="<%= attributes.animaltype %>"/>
                </td>
           </tr>
           <% for (var key in animalTypes) { %>
               <% var typeID= (key).toLowerCase() +"_id" %>
               <tr>
                   <td><%= key %> ID:</td>
                   <% if (attributes.animaltype === key) { %> 
                       <td>
                           <input value="<%= attributes[typeID] %>" name="<%= typeID %>" type="text"/>
                       </td>
                   <% } else { %>
                       <td>
                           <input value="" name="<%= typeID %>" type="text"/>
                       </td>
                   <% } %>
               </tr>
           <% } %>
    </tbody>
</table>

The part the solves your immediate problem is:

<input value="<%= attributes[typeID] %>" name="<%= typeID %>" type="text"/>

Updated demo: http://jsfiddle.net/ambiguous/qj3ru1mL/1/

Upvotes: 1

Birgit Martinelle
Birgit Martinelle

Reputation: 1889

It's actually quite straight forward

EDIT use arguments[0][typeId]

 <input value="<%= arguments[0][typeID] %>" name=<%= (key).toLowerCase() +"_id"%> type="text"/>

Don't use eval, even if no one screams at you ;) Here's a link to the working fiddle: http://jsfiddle.net/j872q5gm/1/

Thanks @Adrian Lynch for reminding me to be a good JS citizen ;)

Upvotes: 1

Related Questions