1Tips and Tricks 2=============== 3 4.. highlight:: html+jinja 5 6This part of the documentation shows some tips and tricks for Jinja 7templates. 8 9 10.. _null-master-fallback: 11 12Null-Master Fallback 13-------------------- 14 15Jinja supports dynamic inheritance and does not distinguish between parent 16and child template as long as no `extends` tag is visited. While this leads 17to the surprising behavior that everything before the first `extends` tag 18including whitespace is printed out instead of being ignored, it can be used 19for a neat trick. 20 21Usually child templates extend from one template that adds a basic HTML 22skeleton. However it's possible to put the `extends` tag into an `if` tag to 23only extend from the layout template if the `standalone` variable evaluates 24to false which it does per default if it's not defined. Additionally a very 25basic skeleton is added to the file so that if it's indeed rendered with 26`standalone` set to `True` a very basic HTML skeleton is added:: 27 28 {% if not standalone %}{% extends 'master.html' %}{% endif -%} 29 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 30 <title>{% block title %}The Page Title{% endblock %}</title> 31 <link rel="stylesheet" href="style.css" type="text/css"> 32 {% block body %} 33 <p>This is the page body.</p> 34 {% endblock %} 35 36 37Alternating Rows 38---------------- 39 40If you want to have different styles for each row of a table or 41list you can use the `cycle` method on the `loop` object:: 42 43 <ul> 44 {% for row in rows %} 45 <li class="{{ loop.cycle('odd', 'even') }}">{{ row }}</li> 46 {% endfor %} 47 </ul> 48 49`cycle` can take an unlimited amount of strings. Each time this 50tag is encountered the next item from the list is rendered. 51 52 53Highlighting Active Menu Items 54------------------------------ 55 56Often you want to have a navigation bar with an active navigation 57item. This is really simple to achieve. Because assignments outside 58of `block`\s in child templates are global and executed before the layout 59template is evaluated it's possible to define the active menu item in the 60child template:: 61 62 {% extends "layout.html" %} 63 {% set active_page = "index" %} 64 65The layout template can then access `active_page`. Additionally it makes 66sense to define a default for that variable:: 67 68 {% set navigation_bar = [ 69 ('/', 'index', 'Index'), 70 ('/downloads/', 'downloads', 'Downloads'), 71 ('/about/', 'about', 'About') 72 ] -%} 73 {% set active_page = active_page|default('index') -%} 74 ... 75 <ul id="navigation"> 76 {% for href, id, caption in navigation_bar %} 77 <li{% if id == active_page %} class="active"{% endif 78 %}><a href="{{ href|e }}">{{ caption|e }}</a></li> 79 {% endfor %} 80 </ul> 81 ... 82 83.. _accessing-the-parent-loop: 84 85Accessing the parent Loop 86------------------------- 87 88The special `loop` variable always points to the innermost loop. If it's 89desired to have access to an outer loop it's possible to alias it:: 90 91 <table> 92 {% for row in table %} 93 <tr> 94 {% set rowloop = loop %} 95 {% for cell in row %} 96 <td id="cell-{{ rowloop.index }}-{{ loop.index }}">{{ cell }}</td> 97 {% endfor %} 98 </tr> 99 {% endfor %} 100 </table> 101