define a variable inside a jsrender template

Go To StackoverFlow.com

0

I need to keep a "colcounter" variable inside the loop that will be used to fill a jsrender template.

Here is my template code

  <script id="datascapeTemplate" type="text/x-jsrender">

<div id="dsViewport">

    <div class="ds-column" style="width:{{:(name.length*100)}}px;">
        <h1 id="datascapeName">{{:name}}</h1>
        <div><span id="dsToggle">toggle</span></div>
    </div>
{{=colcounter}}
    {{for sections}}
    <div class="ds-section">

        <h3>{{:label}}</h3>
        <div class="ds-column" id="start">

        {{for items}}

            {{* if (colcounter > 4){ 
                colcounter = 1;
                }} 
        </div>
        <div class="ds-column" id="start">

            {{* } }}

            {{* 
            if ( data.selected || datascape.showInvisible) {  }}     
            <div class="ds-item {{* if (data.featured){ }} nowActive {{*} }} {{* if (data.active){ }} nowActiveRed {{*} }}"  background="{{:background}}" bgcolor="#000000" fgcolor="#FFFFFF">
                <div class="ds-item-container">
                    <h4>{{:title}}<br/>{{:time}}</h4>

                    <p><a item="{{:id}}" href="{{:url}}" class="itemLink">view file {{:colcounter}}</a></p>
                </div>
            </div>

            {{* colcounter++; }}

            {{* } }}

        {{/for}}
        </div>
        {{* colcounter=1; }}
        </div>
    {{/for}}
    {{* colcounter=1; }}
</div>


</script>

Unfortunately, it prints, on the very first iteration of the loop "Error: colcounter is not defined.". Afterwards it works.

It seems the way i initialise my colcounter variable is not working but i fail to find the correct way. var colcounter =0 does not work.

UPDATE

  • jsfiddle: http://jsfiddle.net/ZX6Mk/
  • colcounter works now. I declared it in the global scope. But I have an issue with datascape.showInvisible. It also triggers the error Error: Cannot read property 'showInvisible' of undefined.

Thank you for your time, a.

2012-04-04 21:33
by pixeline
Can you create a fiddle on jsfiddle.net with your example, including your javascript please? Your HTML and template suggest a few issues. First, the {{=colcounter}} likely should be {{:colcounter}} if you intend to display that value. Rendering a value in jsrender is done with the token like this {{:myVal}} . Second, its not obvious if colcounter is part of the data context for the template, a javascript variable defined outside of the template (which won;t work unless you pass it in as data), or a variable you want to define inside the template only - John Papa 2012-04-06 02:33
I am guessing colcounter is a variable you want created and used only within the template. Before we go there, I highly recommend you change the template to not use allowCode and instead use some helper functions. The if statements could easily be written to use helpers. But show us a full example in jsfiddle, and I can help you more - John Papa 2012-04-06 02:38
Hello, thank you for the comments. Here is the fiddle: http://jsfiddle.net/ZX6Mk - pixeline 2012-04-07 15:46
thanks, i'll post the answer shortly - John Papa 2012-04-08 15:03


3

I took your fiddle and made a few changes. http://jsfiddle.net/johnpapa/bLSkz/

  1. The toggleButton was being referred to in jQuery without the #. So I added that.List item, otherwise the click was not being captured.
  2. Your fiddle did not reference jQuery nor JsRender, though you were using both, so I added them. (I assume you never ran the fiddle)
  3. There was no datascape.showInvisible property, so I created one.
  4. I passed showInvisible to the inner for loop using a parameter, so it could be accessed in its context.

    {{for sections ~showIt=showInvisible}}
    
    {{if (editorspick_amount > 0 || ~showIt)}}
    
  5. The template you were trying to render did not exist, so I changed the rendering code to use the script tag you created. This also sets the allowCode=true, which is required to safely turn on the allowCode feature.

    $.templates("myTmpl", {markup: "#datascapeTemplate", allowCode: true });
    
    $('#toggleButton').click(function(){
        if(!rendered){
            rendered = true;
            $("#datascape").html(
                $.render.myTmpl( datascape.json )
            ).show();
        }
    });
    
  6. I changed one place where you used {{* }} to instead use an {{if}} block since there was no need to use allow code.

This allowed all of the code to run and the template to render, though I admittedly did not follow all of what you were trying to do.

Hope this helps.

One suggestion ... the allowCode feature makes for really ugly templates and hard to maintain and read. I highly recommend replacing it with helper functions (or other constructs). For example, you used allowCode to create the styling for some elements. You could have used a custom tag for this instead, and moved the logic to javascript and simplified your template. The colcounter could be moved to a helper function. It's just much more readable to move the logic to javascript, and keep the template/html clean. Just my 2 cents :)

2012-04-08 15:36
by John Papa
Awesome! Thanks a lot for the detailed explanation, i was able to adapt your input to make it work - and learned in the process - pixeline 2012-04-09 19:45
Glad I could help. I'd love to see your final code when you are done, if you could put it in a fiddle and share - John Papa 2012-04-09 21:12
Hi John, i've published the new template here: http://jsfiddle.net/7JGLm/ But i'm having another issue: it works for some json files, not for others, so it's a bit unreliable. I'll update the fiddle to illustrate that - pixeline 2012-04-14 23:36
No, in fact i think my issue is css-related, the jsfiddle works fine. You'll see i used helpers, as you advised - pixeline 2012-04-14 23:45
Glad to hear it worked out - John Papa 2012-04-22 01:46
Ads