I am trying to create an HTML table to display the contents of a mongodb collection. The collection contains data about different customer orders from a small business. Some of the data will always exist in a given document, for example the customer name and phone number. However, some of the pieces of data within each document need to vary, such as items ordered since one customer may order 1 item, while another may order 3 items. So, if I have a mongodb collection with documents that contain an arbitrary number fields in each document, how can I dynamically add them to an HTML table to display the document's contents? As an example of the type of display I am looking for, here is the hard-coded HTML for the fields which I know will remain constant.
<!DOCTYPE html>
<html>
<head>
<head>
<title>Invoice Report</title>
<style type="text/css">
body {font-family:sans-serif;color:#4f494f;}
form input {border-radius: 7.5px;}
h5 {display: inline;}
.label {text-align: right}
.ordersBook {float:left; padding-top: 10px;}
.name {width:100%;float:left; padding:3px;}
.wrapper { padding-left: 25px; padding-top: 20px}
</style>
<script type="text/javascript">
var itemRe = /item*/;
}
</script>
</head>
</head>
<body>
<div class="invoice">
<h4>Order Form:</h4>
<table border="1">
<tr>
<th>Name:</th>
<td>{{rows['name']}}</td>
</tr>
<tr>
<th>Created:</th>
<td>{{rows['created']}}</td>
</tr>
<tr>
<th>Phone:</th>
<td>{{rows['phone']}}</td>
</tr>
<tr>
<th>Email:</th>
<td>{{rows['email']}}</td>
</tr>
<tr>
<th>Item:</th>
<td>{{rows['item']}}</td>
</tr>
</div>
<tr>
<th>Quantity:</th>
<td>{{rows['qty']}}</td>
</tr>
<tr>
<th>Color:</th>
<td>{{rows['color']}}</td>
</tr>
<tr>
<th>Quote:</th>
<td>{{rows['quote']}}</td>
</tr>
</table>
</div>
</body>
</html>
It would probably be better to create the entire table dynamically, but I am not sure where the proper place to do this is
in a javascript function within the HTML file?
Or maybe in the pymongo file which maintains the info in the mongodb database?
The python code which handles sending the mongodb document to the HTML form uses a python Bottle template.
#bottle.route('/view/<_id>', method = 'GET')
def show_invoice(_id):
client = pymongo.MongoClient("mongodb://localhost")
db = client.orders
collection = db.myorders
from bson.objectid import ObjectId
result = collection.find_one({'_id': ObjectId(_id)})
return bottle.template('invoice', rows = result)
I greatly appreciate any help that someone may be able to offer! =)
Looking over the documentation for the bottle template engine, it looks like you can use 'ifs' and 'fors' to accomplish this.
For instance, if you order is stored at rows['orders'] and you don't know how many there are, in your template you can place:
%for item in rows['orders']:
<td>{{item}}</td>
%end
or say that you need to display a special warning if your customer is ordering an item that is frequently on backorder, and you've passed in another variable, 'backorder', that specifies this:
%if backorder:
<span>This item is frequently on backorder</span>
%end
I haven't tested either of these, but I've done similar things using the Django and Flask template engines. I pulled these samples from here:
http://bottlepy.org/docs/dev/tutorial.html#templates
and the 'Bottle Template to Format the Output' section here:
http://bottlepy.org/docs/dev/tutorial_app.html#using-bottle-for-a-web-based-todo-list
Hope this helps!
Related
For a customer we are making a webpages project. This includes a lot of tables with even more records.
I am looking for a client-side way to show only a certain part of the table (be it a TOP 100, records for the past month, something like that), but keeping all the records available for usage by a search filter.
The search filter I am currently using is the one from W3.JS (w3.htmlFilter), but upon loading this still shows over 500 records.
The main objective is described above, but I'd also accept a decent solution which would allow me to display 10 records, without losing the filter optionality.
The table is populated using a foreach that constructs each record based on a collection provided using Razor.
Already tried setting the Table Max-Height and giving it a Y-overflow.
Already tried a display:inline-block, but this destroyed all lay-out.
Already tried some JS, which displayed only certain records, but meant I lost access to the non-displayed records (due to Razor).
To populate my data I use this Razor:
#{
var allFoo = db.GetFoos();
var foosToShow = foos.Where(v => v.SomeCondition == true);
}
The filter applied to the table:
<input id="filter" oninput="w3.filterHTML('#foosTable', '.filterItem', this.value)" class="w3-input" placeholder="Search for foo..." />
actually populating the records:
<tbody>
#foreach (Foo foo in foosToShow)
{
<tr class="filterItem" onclick="TransferElement(this)">
<td>#foo.Prop1</td>
<td>#foo.Prop2</td>
<td>#foo.Prop3</td>
<td>#foo.Prop4</td>
<td>#foo.Prop5</td>
<td>#foo.Prop6</td>
</tr>
}
</tbody>
Expected Result: Filterable List of X records long, where X can be set.
Here is a solution by using datatables:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.js"></script>
</head>
<body>
<script>
var data = [
[
"Tiger Nixon",
"System Architect",
"Edinburgh"
],
[
"Garrett Winters",
"Director",
"Edinburgh"
]
]
$(document).ready( function () {
$('#table_id').DataTable( {
data: data
} );
} );
</script>
<table id="table_id" class="display">
<thead>
<tr>
<th>Name</th>
<th>Job</th>
<th>City</th>
</tr>
</thead>
</table>
</body>
</html>
The only thing you have to change is the variable data to your array with data.
Everything works without server side processing.
What you could also do: Create a getdata.php file and use this one as data source by echoing the query result as JSON.
For further information: https://datatables.net/manual/data/
(First allow me to say that I'm just beginning to learn Node-RED concepts; I went through some beginners' guides at nodered.org, and now am trying to extend what I learned so far).
I'm trying to build a flow that starts with a simple JSON tree like
[{"position":"1", "title":"element #1"},
{"position":"2", "title":"element #2"},
{"position":"3", "title":"element #3"}]
To build that treee I use a template node, property is set to msg.payload.
The number of array elements (in theory) is dynamic. To make sure that this tree is true JSON I added a JSON node converting from String to JSON object.
Next I wish to parse that object into a dynamic html table. For this I used a JS function node that's looping through the object and embedding its elements into the according html elements like this:
var return="";
for(var i=0;i<=msg.payload.length-1;i++){
var row=msg.payload[i];
if(row){
return+="<tr>";
return+="<td>"+row.position+"</td>";
return+="<td>"+row.title+"</td>";
return+="</tr>";
}else{
return+="no object at index "+i.toString();
}
}
msg.payload=return;
return msg;
The output of the function then should be passed into a 2nd template like this:
<html>
<head></head>
<body>
<table border="1">
<tr>
<td>#</td>
<td>Title</td>
</tr>
{{ payload }}
</table>
</body>
</html>
I would have expected that the function's result is inserted into the static table of my template, and that happens indeed but not the way I hoped: somehow the html elements that got created by my function are not recognized as what they shoud be; instead I see that they are rendered as
<tr><td>1</td><
instead of
<tr><td>1</td>
etc.
Result is that the browser does not recognize those elements and prints them together with their contents outside my static table
Questions:
what do I need to do so that my 2nd template recognizes my computed string as a set of html elements?
or is this probably a concept not suitable for my purpose?
I'm assuming you are using handelbars for your templating engine. In that case use:
{{{ payload }}}
Instead of
{{ payload }}
However a more elegant approach would be this:
<html>
<head></head>
<body>
<table border="1">
<tr>
<td>#</td>
<td>Title</td>
</tr>
{{#each payload}}
<tr><td>{{this.position}}</td><td>{{this.title}}</td></tr>
{{/each}}
</table>
</body>
</html>
then just
return msg.payload
again thanks to #als9xd for pointing me into the right direction; his 2nd idea indeed sounds much more elegant but first I couldn't get it to work. After some trial-and-error and looking up documentation for the template node I finally came up with this: removed the function node from my original question and then altered the 2nd template to this code:
<html>
<head></head>
<body>
<table border="1">
<tr>
<td>#</td>
<td>Title</td>
</tr>
{{#payload}}
<tr>
<td>{{position}}</td>
<td>{{title}}</td>
</tr>
{{/payload}}
</table>
</body>
</html>
Difference to #als9xd's example is that I replaced {{#each payload}} with a simple {{#payload}}, plus omitted this when referencing the object keys.
Could this be due to different Node-RED versions?
Anyways this is starting to be much fun!
Im having trouble trying to sort a dynamically created html table. I create it using jade/pug. I am trying to use the sorttable.js script found here http://www.kryogenix.org/code/browser/sorttable/ . I am still kind of new to html/javascript. So if there is some obvious reason why its not working could someone point it out please?
Here is some of the html code generated from the template
<html>
<head>
<script src="/path/to/sorttable.js"></script>
<style>
th.clickable:hover
{
color:green
}
th, td
{
padding:5px;
}
th.clickable
{
cursor: pointer;
}
</style>
</head>
<body>
<script>
var newTableObject = document.getElementById(tbl)
sorttable.makeSortable(newTableObject)
</script>
<table class="sortable" id="tbl">
<tr>
<th class="clickable">id</th>
<th class="clickable">value</th>
</tr>
<tr>
<td>100</td>
<td>100</td>
</tr>
<tr>
<td>200</td>
<td>200</td>
</tr>
</table>
</body>
</html>
The goal is to have it so when I click on the header it sorts the table by that column.
Please excuse if this is already known...but
The script tag gets read and executed whenever the browser comes across it. Have you tried putting the script tag after your table?
At the time your code executes:
var newTableObject = document.getElementById(tbl)
sorttable.makeSortable(newTableObject)
Your table hasn't rendered yet and is unavailable. So you;re passing undefined to the sorttable.makeSortable method. You can test this by adding a trace statement after you get the element:
var newTableObject = document.getElementById(tbl)
console.log(newTableObject)
You should wait to fire this code after your table has rendered. Something like this:
onLoad = function(){
var newTableObject = document.getElementById(tbl)
sorttable.makeSortable(newTableObject)
}
and declare that like so:
// using jQ
$(document).ready( onLoad())
or for plain JS
<body onload="onload()">
Hi I am totally stuck on this one.
I am using tablesorter on data pulled from a mysql database.
The problem is, based on criteria, I can have multiple tables pulled and displayed.
My problem is that tablesorter will only sort the first table instance.
This is the code I am using for the tablesorter. Basic use of it.
<script type="text/javascript" >
$(document).ready(function()
{
$("#table-2").tablesorter();
}
And this is how I pull the data and use it with tablesorter.
It is the Branchname that can change. If a user is assigned more than one branch they get multiple tables. This is where I'm stuck on implementing tablesorter on any table past the first instance.
$result=mysql_query("SELECT id FROM users WHERE username='$username'");
$idary=mysql_fetch_assoc($result);
$id=$idary['id'];
$result0=mysql_query("SELECT branch_id FROM access WHERE userid='$id'");
while ($row1=mysql_fetch_assoc($result0))
{
$branch_id=$row1['branch_id'];
$result=mysql_query("select distinct(name) from location where id='$branch_id'");
$nameary=mysql_fetch_assoc($result);
$branchname=$nameary['name'];
?>
<table>
<thead>
<b><br><?echo $branchname; ?></b>
</thead>
</table>
<div>
<table id='table-2' class='tablesorter'>
<thead>
<tr>
<thCreator</th>
<th><center>TeamName</th>
<th><center>Tech Tot</th>
<th><center>Tot W/O</th>
<th><center>Tot S/C</th>
</tr>
</thead>
// get team creators from province
$result1=mysql_query("select distinct(teamcreator) from techteams where....
I'm thinking I would need to use some form of incrementing tablename to match the number of tables pulled but I'm stuck on how to do this.
I could be wrong on that assumption and there might be a much easier way of doing this.
If anyone has any pointers in the right direction I'd love some tips.
Cheers,
-Colin.
you could try to give your tables an own class instead of an id.
<table class='mytables'>
<script type="text/javascript" >
$(document).ready(function()
{
$(".mytables").tablesorter();
}
</script>
or maybe only give them the table-sorter class and in your script you try something like this:
$("table").tablesorter();
Try it:
$(".tablesorter").tablesorter();
Been searching for answers but finding none. I have a code that displays a table pulled from a server-side genqueuesearch.php based on a parameter "rg1". Each row has a column called Queue with an "rg1" string in it. The table has several columns but my challenge is displaying only 4 columns. Here is my AJAX code:
<html>
<head>
<script language="Javascript">
function View(){
...
xmlhttp.onreadystatechange=function(){
if (xmlhttp.readyState==4 && xmlhttp.status==200){
document.getElementById("datatable").innerHTML=xmlhttp.responseText;
}
}
var parameters = "search="+"rg1";
xmlhttp.open("POST", "http://drcsblr0165/genqueuesearch.php", true);
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlhttp.send(parameters);
}
</script>
</head>
<body onload="View()">
<div id="datatable" align="center"></div>
</body>
</html>
Tried getElementsbyTagName but I don't know the tag names for the columns I would like. Does this require saving the table to a text file first? I appreciate all your help and please ask if I'm not clear.
Since you can't alter what the server is giving you, then we are restricted to solving this with JavaScript only. I do suggest you use jQuery because it'll make things much simpler for you.
jQuery utilizes CSS selector pattern for finding elements in the DOM. You can leverage it to select which columns in the table you'd like to hide. You can even select specific columns even if you don't know the name of them.
Say, you get back a table like this from the server and you've put it inside your <div id="datatable">:
<div id="datatable" align="center">
<table>
<tr>
<td>dataRow1Col1</td>
<td>dataRow1Col2</td>
<td>dataRow1Col3</td>
<td>dataRow1Col4</td>
</tr>
<tr>
<td>dataRow2Col1</td>
<td>dataRow2Col2</td>
<td>dataRow2Col3</td>
<td>dataRow2Col4</td>
</tr>
<tr>
<td>dataRow3Col1</td>
<td>dataRow3Col2</td>
<td>dataRow3Col3</td>
<td>dataRow3Col4</td>
</tr>
<tr>
<td>dataRow4Col1</td>
<td>dataRow4Col2</td>
<td>dataRow4Col3</td>
<td>dataRow4Col4</td>
</tr>
</table>
</div>
For example, using the :nth-child selector doesn't require you to know the class name, $('#datatable td:nth-child(3)').hide(); will select the 3rd column and hide it. (see example: http://jsfiddle.net/Cjsua/)
You may find more suitable selectors on the jQuery documentation: http://api.jquery.com/category/selectors/
The .hide() function simply hides the elements matched.