1

I've been searching and reading for a while now, and I'm just not grasping what I'm missing. I'm hoping you can help.

I've got a JSON data structure that contains two arrays: the first is a list of clients, and the second is a list of 'affected' clients:

var data = {
    allClients:      [ 
                       {clientId: 1, clientName: "Client One"},
                       {clientId: 2, clientName: "Client Two"},
                       {clientId: 3, clientName: "Client Three"},
                       {clientId: 4, clientName: "Client Four"},
                       {clientId: 5, clientName: "Client Five"},
                       {clientId: 6, clientName: "Client Six"},
                       {clientId: 7, clientName: "Client Seven"},
                       {clientId: 8, clientName: "Client Eight"}
                     ],
    clientsAffected: [ 1, 2, 5, 8 ]
};

I am using a simple jsRender template to create a select box, using the allClients array :

<script id="tmpl" type="text/x-jquery-tmpl">
  <select name="clients" id="clients" style="150px;" size=10 multiple>

{{for allClients}}
    <option value="{{:clientId}}">{{:clientId}} - {{:clientName}}</option>
{{/for}}

  </select>

</script>

This is working fine... produces a simple select box.

What I am trying to do (unsuccessfully) is to add a 'selected' attribute to the option that is rendered, so that in my example options 1, 2, 5, and 8 from clientsAffected are selected when the control is generated. I've been attempting to put another loop inside of the existing one, to iterate over the clientsAffected array and compare one value to the other, but I'm not having any success.

Has anyone done this before, or can you point me to a good document that describes what I need?

I've created a jsFiddle that represents what I have working: http://jsfiddle.net/LcSn7/17/

and one that is not that hopefully shows the direction I'm trying to go: http://jsfiddle.net/LcSn7/19/

Thanks in advance! -Tim

2 Answers 2

2

As an alternative to Jacob's suggestion, here is one approach, using a helper function. (In fact helper functions in effect allow conditionals to access more complex logic such as accessing loops etc.):

{{for allClients}}
    <option value="{{:clientId}}" {{:~isSelected(clientId)}}>
        {{:clientId}} - {{:clientName}}
    </option>
{{/for}}

with:

$("#container").html($("#tmpl").render(data, {isSelected: function(id) {
    return $.inArray(id, data.clientsAffected) > -1 ? 'selected="selected"' : ""
}}));

See updated version of your fiddle: http://jsfiddle.net/LcSn7/20/

You might also be interested in this, using JsViews: http://www.jsviews.com/#samples/tag-controls/multiselect

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks Boris. This is the answer I needed, and having a 'conceived by me' example of how to use helper functions will also be useful. I struggle sometimes applying someone else's example to my own problems.
1

You cannot with jsRender as-is, because it's conditionals lack the ability to check within loops or against other objects.

What you have is quite right, except for variable scoping; you need to scope within the {{for}} statement. See this question: "Access parent item inside a loop in jsrender".

But without equality conditional you need, you need to reorganize the data. Here's my suggestion, first add a boolean affected property to allClients, using the data you already have, like so:

for (var i = 0; i < data.allClients.length; i++){
    data.allClients[i].affected = (jQuery.inArray(data.allClients[i].clientId, data.clientsAffected) != -1);
}

Than from within your jsRender template, you can use simple truth conditionals:

<option value="{{:clientId}}" {{if affected}}selected="selected"{{/if}}>

My JSFiddle.

1 Comment

Jacob, thanks for your answer. I'm going to accept BorisMoore's answer since I think the concept of a helper function will be more useful to me going forward, but pre-processing is a useful approach.

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.