Here is my problem. I have the following function
def index():
rows=db(db.mylist).select()
return dict(rows=rows)
so whenever I reload the the front view index I want to retrieve rows from the database and display the data to the user in a list
{{for(r in rows)}}
li.innerhtml={{=rows.task}}
{{pass}}
Obviously, this is not the right way to do it. I think I have to use json and XML.
This is the table I am using
db.define_table(
'mylist',
Field('task', 'string')
)
<div class="col-sm-6">
<div class="panel panel-default">
<div class="panel-heading center " style="color: black; font-style: inherit">
<form>
Task:
<input name="name" id="task" />
<button type="button" class="btn btn-success btn-sm" onclick=add(),ajax('{{=URL('default','insert_task')}}',['name']) >add</button>
</form>
</div>
<div class="panel-body center">
<ul id="list" class="list-group"> </ul>
</div>
</div>
</div>
</div>
var ul = document.getElementById("list");
var lastId=0;
function add()
{
if(!isBlank(document.getElementById("task").value)) {
var iCon = document.createElement('div'); //create a div container
var dbtMenu=document.createElement('div');
var li = document.createElement("il"); //create a list-element
var closeSpan = document.createElement("span"); //create a span for badge attribute
var ClickListState=0;
dbtMenu.setAttribute("class","container");
//dbtMenu.appendChild(dropDownList);
li.setAttribute('id',lastId); // set an attribute for id
iCon.className = "glyphicon glyphicon-remove"; // image for remove button
closeSpan.setAttribute("class", "badge"); //create a new attribute for span
closeSpan.appendChild(iCon); // put it in the span set
iCon.addEventListener("click",function(){var element=document.getElementById(li.getAttribute('id'));
element.parentNode.removeChild(element);}); //functionlity
li.innerHTML = document.getElementById('task').value;
var value=document.getElementById('task').value;
var pass= document.getElementById('task').value;
li.setAttribute("class", "list-group-item hover-yellow");
li.addEventListener('click',function() {if(ClickListState==0){li.style.backgroundColor="red"; ClickListState++;}
else {li.style.backgroundColor="white"; ClickListState--; }});
li.appendChild(closeSpan);
lastId++;
ul.appendChild(li);
}
}
function update()
{
{{for r in rows:}}
var iCon = document.createElement('div'); //create a div container
var dbtMenu = document.createElement('div');
var li = document.createElement("il"); //create a list-element
var closeSpan = document.createElement("span"); //create a span for badge attribute
var ClickListState = 0;
dbtMenu.setAttribute("class", "container");
//dbtMenu.appendChild(dropDownList);
li.setAttribute('id', lastId); // set an attribute for id
iCon.className = "glyphicon glyphicon-remove"; // image for remove button
closeSpan.setAttribute("class", "badge"); //create a new attribute for span
closeSpan.appendChild(iCon); // put it in the span set
iCon.addEventListener("click", function () {
var element = document.getElementById(li.getAttribute('id'));
element.parentNode.removeChild(element);
});
// var t ={#{=XML(response.json(r.task))}}
li.innerHTML = "t";
var value = document.getElementById('task').value;
var pass = document.getElementById('task').value;
li.setAttribute("class", "list-group-item hover-yellow");
li.addEventListener('click', function () {
if (ClickListState == 0) {
li.style.backgroundColor = "red";
ClickListState++;
}
else {
li.style.backgroundColor = "white";
ClickListState--;
}
});
li.appendChild(closeSpan);
lastId++;
ul.appendChild(li);
{{pass}}
}
update();
2 Answers 2
Read the basic syntax for template language in web2py here
You want this:
<ul>
{{for row in rows:}}
<li>{{=row}}</li>
{{pass}}
</ul>
Other solution can be, build the complete list in controller function using html helpers and pass it to view
def index():
rows = db(db.mylist).select()
my_list = [row.task for row in rows]
task_list = UL(*my_list)
return dict(task_list=task_list)
And in the view just do:
{{=XML(task_list)}}
XML is an object used to encapsulate text that should not be escaped.
I will suggest you to go through these 2 examples: Image blog and Simple wiki
EDIT:
From your edit, I think you want to add new task using form and wanted to add the list without refreshing the page.
Read Ajax form submission, also related ajax example is given in simple wiki app
<!-- Views/index.html-->
{{extend 'layout.html'}}
<form id="task_form">
Task:
<input name="name" id="task" />
<input type="submit" class="btn btn-success btn-sm" value="Add" />
</form>
<div id="target"> {{=XML(task_list)}}</div>
<script>
jQuery('#task_form').submit(function() {
ajax('{{=URL("default", "insert_task")}}',
['name'], 'target');
return false;
});
</script>
--
# Controller
def index():
rows = db(db.mylist).select()
my_list = [row.task for row in rows]
task_list = UL(*my_list)
return dict(task_list=task_list)
def insert_task():
"""an ajax callback that returns a <ul>"""
task_name = request.vars.name
db.mylist.insert(task=task_name)
rows = db(db.mylist).select()
my_list = [row.task for row in rows]
task_list = UL(*my_list)
return task_list
10 Comments
<li> elements via Python (given that you are looping through all the list elements on the server before any Javascript even gets executed in the browser)? If you really need to process everything via Javascript, then just use web2py to write some Javascript data structure into the page and handle all the processing with Javascript.insert_task function will add that value in database and also will return new updated task list which will be inserted in target div. If u refresh the index page then anyway all the task will be returned and will shown in list format. there is no need of add() and update() js functions. Let me know if this solve your issue or notI came up with this to convert a python list of strings to a javascript array of strings:
{{def print_js_array(left_side, pylist):
wrap_quotes = map(lambda a: "'{}'".format(a), pylist)
comma_separated = "" if not pylist else reduce(lambda a,b: "{}, {}".format(a,b), wrap_quotes)
return "{} = [{}];".format(left_side, comma_separated)
}}
{{=SCRIPT(
""
+ print_js_array("var un_pythoned", status_filter_options))
}}
Which given a python list ['', 'Not Started', 'Running', 'Finished', 'Failed'] results in (html):
<script><!--
var un_pythoned = ['', 'Not Started', 'Running', 'Finished', 'Failed'];
//--></script>
Making the array available to subsequent scripts. You could probably write something similar to print a dictionary as json.
{{...}}delimiters) gets executed on the server before the page is delivered to the browser. So, your Python code cannot interact with Javascript code (which is executed in the browser after the full page has been processed by web2py). In other words, you cannot have a Python loop that runs some Javascript code within the loop. You will need to explain in more detail what you are trying to achieve.