Nested tempaltes which are not evaluated.

42 views
Skip to first unread message

Tonis Piip

unread,
Jan 17, 2018, 6:09:42 AM1/17/18
to brython
I have a template which generates my HTML, however I'm wanting to have another template inside the rendered template which is not rendered on initial rendering for example

  <div id="template" b-code="for x in data">
     
<div>
         
<div>{data['value']}</div>
         
<ul class="hidden">
             
<li class="second-template" b-code="for r in rows">
                  {r['value']}
             
</li>
         
</ul>
     
</div>
 
</div>

If I don't include a rows argument to the render method the rendering will fail.
If want to have the ul be filled in later, for example in an AJAX callback, I have to edit the template as follows and have a method which edits the HTML.


  <div id="template" b-code="for x in data">
     
<div>
         
<div>{data['value']}</div>
         
<ul class="hidden">
             
<li class="second-template">
             
</li>
         
</ul>
     
</div>
 
</div>

Template.render("template", data = [...])
jq
.(".second-template").attr("b-code", "for r in rows").text("{r['value']}")



Is there any way to render a template so that it doesn't evaluate a template block, but will render into a valid template block?


Pierre Quentel

unread,
Jan 18, 2018, 3:45:35 PM1/18/18
to brython


Le mercredi 17 janvier 2018 12:09:42 UTC+1, Tonis Piip a écrit :
I have a template which generates my HTML, however I'm wanting to have another template inside the rendered template which is not rendered on initial rendering for example (...)

Is there any way to render a template so that it doesn't evaluate a template block, but will render into a valid template block?

I have slightly modified your example:

<div id="template">
 
<div b-code="for x in data">
     
<div>{x}</div>

     
<ul class="hidden">
         
<li class="second-template" b-code="for r in rows">

              {r}
         
</li>
     
</ul>
 
</div>
</div>

<button id="fill-rows">Fill rows</button>

<script type="text/python">
from browser
import document, window, alert
from browser
.template import Template

data
= ["one", "two"]

tmpl
= Template("template")
tmpl
.render(data=data, rows=[])

@document["fill-rows"].bind("click")
def click
(evt):
    rows
= ["alpha", "beta", "gamma"]
    tmpl
.render(data=data, rows=rows)
</script>


The template is rendered first with an empty list for rows. When the user clicks on the "Fill rows" button (which simulates an Ajax call), the template is rendered again by calling its render() method, with a new value for rows.

Does this make sense for your use case ?

Tonis Piip

unread,
Jan 21, 2018, 3:22:26 PM1/21/18
to brython
I understand what your solution is trying to do but no, it doesn't solve the issue.

The use case is the following.

An ajax query's returned data-data fills in a template that has a for loop.
A second ajax query is potentially called in order to add more data to the initial template. Either a table, action buttons, select options, etc.

Your solution fails since the rows iterator is the same for each item in the original list.
Also it requires re-rendering of the whole list, rather then just rendering of new data, and if there are JS elements that require initialization, it has to be done after the re-render.

Pierre Quentel

unread,
Jan 23, 2018, 4:13:45 AM1/23/18
to brython


Le dimanche 21 janvier 2018 21:22:26 UTC+1, Tonis Piip a écrit :
I understand what your solution is trying to do but no, it doesn't solve the issue.

The use case is the following.

An ajax query's returned data-data fills in a template that has a for loop.
A second ajax query is potentially called in order to add more data to the initial template. Either a table, action buttons, select options, etc.

Your solution fails since the rows iterator is the same for each item in the original list.

It was because in your first example, the list rows was the same inside each for loop. The following code simulates different values:

from browser import document
from browser.template import Template

data
= {

   
"one": {
       
"rows": []
   
}, "two": {
       
"rows": []

   
}
}

tmpl
= Template("template")

tmpl
.render(data=data)

@document["fill-one"].bind("click")
def click(evt):
    data
["one"]["rows"] = ["alpha", "beta", "gamma"]
    tmpl
.render(data=data)

@document["fill-two"].bind("click")
def click(evt):
    data
["two"]["rows"] = ["Mercure", "Vénus", "Terre"]
    tmpl
.render(data=data)


Also it requires re-rendering of the whole list, rather then just rendering of new data, and if there are JS elements that require initialization, it has to be done after the re-render.

Can't this be done inside the callback function associated with the Ajax call, after re-rendering the template ?
Reply all
Reply to author
Forward
0 new messages