Search code examples
javascriptjqueryjsonjsrender

How to access parent data properties in JsRender nested templates


http://jsfiddle.net/tQnVt/621/

This fiddle illustrates my problem.

Say I am binding a JSON onto view with the help of jsrender templates.

var vm = {
    foo: {color: "red",otherObjectToMatch:"object"},
    testData: [{color: "red"}, {color: "yellow"}, {color: "blue"}]
};

Object vm has 2 properties- 1) a plain object 2) array of objects.

Template-

<script id="template" type="text/x-jsrender">
    <p>
    {{:foo.color}}
    </p>
    <ul>
    {{for testData}}
        <li>index: {{>color}}</li>
    {{/for}}
    </ul>
</script>

I want to match from plain object #1 by its property where if its property color matches with the property in loop then will apply some class.

I tried-

 <p>
    {{:foo.color}}
    </p>
    <ul>
    {{for testData}}
       {{if foo.color=={{>color}} }}
         <li class='match'>index: {{>color}}</li>
       {{else}}
         <li>index: {{>color}}</li>
       {{/if}}
    {{/for}}
    </ul>

This is a failed try. I can't find how to match with other objects in jsrender.


Solution

  • You need to write

    {{if xxx.foo.color===color}}
    

    where xxx is the parent data - in your case the vm you passed in as root data.

    (It's all about the 'view hierarchy' - see: http://www.jsviews.com/#views. See also the specific topic Accessing parent data)

    Here are several different ways to get to the data on the parent view:

    Access ~root which is a shortcut helper for the root data:

    {{for testData}}
       {{if ~root.foo.color===color}} 
         <li class='match'>index: {{>color}} (match)</li>
       {{else}}
         <li>index: {{>color}}</li>
       {{/if}}
    {{/for}}
    

    Create a contextual template parameter ~foo to pass the foo property from parent data through to the nested template contexts:

    {{for testData ~foo=foo}}
       {{if ~foo.color===color}}
         <li class='match'>index: {{>color}} (match)</li>
       {{else}}
         <li>index: {{>color}}</li>
       {{/if}}
    {{/for}}
    

    Step up through the parent view objects, and get the data view:

    {{for testData}}
       {{if #parent.parent.data.foo.color===color}}
         <li class='match'>index: {{>color}} (match)</li>
       {{else}}
         <li>index: {{>color}}</li>
       {{/if}}
    {{/for}}
    

    Use the view.get() helper to find the parent of view of type "data"

    {{for testData}}
       {{if #get("data").data.foo.color===color}}
         <li class='match'>index: {{>color}} (match)</li>
       {{else}}
         <li>index: {{>color}}</li>
       {{/if}}
    {{/for}}
    

    I added all of them to your jsfiddle: http://jsfiddle.net/tQnVt/625/

    See also this related reply: https://stackoverflow.com/a/34441881/1054484