0

Trying to convert very complex jQuery template code to jsRender. I have this each loop in the old code:

<script id = "imagesTemplate" type="text/x-jquery-tmpl">
    {{each(i,imgUrl) twoAcross_filterOutMainImages(OfferGroup.Images)}}
        <img src="{{= imgUrl}}" />
    {{/each}}
</script>

<script id = "largeTemplate" type="text/x-jquery-tmpl">
    {{tmpl "#imagesTemplate"}}
</script>

<div id="LARGE"  class="mainContent"></div>
<script>
     currentOffer = offerGroups[0].Groups[0];
     $( "#LARGE" ).html( $( "#largeTemplate" ).render( currentOffer ) ); 
</script>

I have edited it to look like this:

{{for ~filterOutMainImages(Images) tmpl="#imagesTemplate"/}}

<div id="LARGE"  class="mainContent"></div>
<script>
     currentOffer = offerGroups[0].Groups[0];
     $( "#LARGE" ).html( $( "#largeTemplate" ).render( currentOffer ) ); 
</script>

But it does not work. If I change it to be:

<script id = "imagesTemplate" type="text/x-jquery-tmpl">    
        <img src="{{= imgUrl}}" />
</script>

<script id = "largeTemplate" type="text/x-jquery-tmpl">
    {{for Images tmpl="#imagesTemplate"/}}
</script>

<div id="LARGE"  class="mainContent"></div>
<script>
     currentOffer = offerGroups[0].Groups[0];
      $( "#LARGE" ).html( $( "#largeTemplate" ).render( currentOffer ) ); 
</script>

It draws the images to display but the function does not run on the image array. But if I leave the Images array without being wrapped in a function and move the for loop to inside the template it breaks.

How would I convert this scenario?

2
  • How are you declaring your helper function: filterOutMainImages? Yes, showing a fiddle would be good... Should be {{:imgUrl}}. That second version above is missing a <script> wrapper around the template... Commented Oct 29, 2013 at 19:12
  • I had a problem with setting it all up using fiddle interface so I posted a test page here: mcgrathdesigns.com/test Commented Oct 30, 2013 at 19:17

1 Answer 1

1

An important difference between JsRender and jQuery Templates is that JsRender does not let you access global functions or variables directly within template markup.

This is a design choice, related to security concerns, and separation of concerns. But unlike "logicless" template languages, such as Mustache, JsRender provides very powerful and flexible support for logic within the template - while still preventing random mixing of code and markup.

One way to include logic is to encapsulate it outside the template in helper functions, but in that case you need to register the helper function, either globally, or for the specific template, or else pass it in on an options object with the render call.

See www.jsviews.com/#helpers and www.jsviews.com/#samples/jsr/helpers for documentation. (There are many other samples also on the www.jsviews.com site showing use of helper functions)

So in your case you can do

function filterOutMainImages(images) { ... }

// Register helper
$.views.helpers({
    filterImages: filterOutMainImages 
});    

var html = $("#largeTemplate").render(currentOffer);

$("#LARGE").html(html);

Or

function filterOutMainImages(images) { ... }

var html = $("#largeTemplate").render(
    currentOffer,
    {filterImages: filterOutMainImages} // Pass in helper
);

$("#LARGE").html(html);

Assuming your filterOutMainImages() function returns a filtered array, and with your helper registered or passed in as above, then the following templates should work:

<script id = "imagesTemplate" type="text/x-jsrender">    
    <img src="{{>imgUrl}}" />
</script>

<script id = "largeTemplate" type="text/x-jsrender">
    {{for ~filterImages(Images) tmpl="#imagesTemplate"/}}
</script>
Sign up to request clarification or add additional context in comments.

4 Comments

Actually Boris if you look at my test page it still seems to not be working. mcgrathdesigns.com/test Is it the way I am writing the array? It actually looks like it may be the way I am trying to call each item in the loop. there does not seem to be an "handle EACH as..." I have written out a commented line in the top of the #LARGE div that shows the array is getting to the for loop.
got it just used #view.data as if it were array[i]in a for loop or each as in an each loop. So in your above example {{>imgUrl}} should be {{:#view.data}}
Well if your function returns an array of strings, it would be {{:#data}} - which is shorthand for {{:#view.data}}. Or you can encode using {{>#data}}, {{attr:#data} or {{url:#data}} - see jsviews.com/#converters(). I had assumed you returned an array of objects with imgUrl properties, given your previous versions.
wow awesome sophistication of your library! Nice to have those options, great job. Thanks again.

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.