define a variable inside a jsrender template-Collection of common programming errors


  • pixeline

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

    Here is my template code

      
    
    
    
        
            

    {{:name}}

            toggle
        
    {{=colcounter}}
        {{for sections}}
        
    
            

    {{:label}}

            
    
            {{for items}}
    
                {{* if (colcounter > 4){ 
                    colcounter = 1;
                    }} 
            
            
    
                {{* } }}
    
                {{* 
                if ( data.selected || datascape.showInvisible) {  }}     
                
                    
                        

    {{:title}}
    {{:time}}

    
                        
    view file {{:colcounter}} {{* colcounter++; }} {{* } }} {{/for}} {{* colcounter=1; }} {{/for}} {{* colcounter=1; }}

    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.


  • Steve B

    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 🙂