Jinja table, when column == value then add div to specific column - javascript

I have a flask app with a jinja table, one of the columns has the value = 1 when that row meets a criteria.
For every row that a 1 is present in that column i would like to replace it with a circle, for example:
How would I add it to my jinja table?
<table>
<thead>
<tr>
{% for col in column_names %}
<th>
{{col}}
</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for row in row_data %}
<tr>
{% for col, row_ in zip(column_names, row) %}
{% if loop.index == 1 %}
<td>
IF {{ row[16] }} == 1 then <div class="circle" style="float: left;">LB</div>
else ''
end
{{row_}}</td>
{% else %}
<td>{{row_}}</td>
{% endif %}
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
HTML/CSS code of div i want to appear in that cell
.circle
{
width:20px;
height:20px;
border-radius:10px;
font-size:8px;
color:#fff;
line-height:20px;
text-align:center;
background:#000
}
<div class="circle" style="float: left;">LB</div>

Solution
Try the following.
The one-line if-else statement in jinja2 looks like this:
{{ OUTPUT_WHEN_TRUE if condition else OUTPUT_WHEN_FLASE }}
So, in your case, the code within for each <td></td> (where loop.index == 1 over the inner loop) will look like this:
{{ '<div class="circle" style="float: left;">LB</div>' if row[16] == 1 else '' }} {{ row_ }}
Code
<table>
<thead>
<tr>
{% for col in column_names %}
<th>
{{col}}
</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for row in row_data %}
{% set row_loop = loop %}
<tr>
{% for col, row_ in zip(column_names, row) %}
{% set col_loop = loop %}
{# Choose which loop: row or col you are referring to #}
{% if col_loop.index == 1 %}
<td>
{{ '<div class="circle" style="float: left;">LB</div>' if row[16] == 1 else '' }} {{ row_ }}
</td>
{% else %}
<td>{{ row_ }}</td>
{% endif %}
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
References
Get loop index of outer loop
Jinja Docs - Accessing the parent Loop
Jinja shorthand conditional: one-line if-else

Related

Dropdown filtering objects in django template using javascript

I have a table that shows details about all the assets. I want the records in the table to be filtered on the basis of different attributes of the table. For now I have tried to create a filter on currentOwner field using JavaScript, but it is not working.
Here is the html file:
{% extends "assets/base.html" %}
{% block content %}
<div class="container">
<legend class="border-bottom mb-4">Hello {{ request.user }}</legend>
</br>
<table class="table" id="admin-asset-table">
<tr>
<th>Asset ID</th>
<th>Asset Type</th>
<th>Asset Name</th>
<th>Brand</th>
<th>Is Active</th>
<th>
<select id="searchddl" onclick="searchOwner();">
<option disabled="true" selected>-- Current Owner --</option>
{% for user in users %}
<option value="{{asset.currentOwner}}">
{{user.username}}
</option>
{% endfor %}
</select>
</th>
<!-- <th>Current Owner</th> -->
</tr>
{% for asset in assets %}
<tr>
<td>{{ asset.id }}</td>
<td>{{ asset.asset_type }}</td>
<td>{{ asset.asset_name }}</td>
<td>{{ asset.brand }}</td>
<td>{{ asset.isActive }}</td>
<td>{{ asset.currentOwner }}</td>
</tr>
{% endfor %}
</table>
</div>
<script type="text/javascript">
function searchOwner()
{
var input,table,tr,td,filter,i;
input=document.getElementById("searchddl");
filter=input.value.toUpperCase();
table=document.getElementById("admin-asset-table");
tr=table.getElementsByTagName("tr");
for(i=0; i<tr.length; i++)
{
td=tr[i].getElementsByTagName("td")[3];
if(td)
{
displaydata=td.innerText;
if(displaydata.toUpperCase().indexOf(filter)>-1)
{
tr[i].style.display="";
}
else
{
tr[i].style.display="none";
}
}
}
}
</script>
{% endblock content%}
Please let me know what is wrong with this. Also let me know if there is any possible way to apply multiple filters of this kind.

Looping through table rows with if conditions in tbody

I have the following html
{% extends "layout.html" %}
{% block title %}
Index
{% endblock %}
{% block main %}
<div>
<table class="table table-striped" id="mytab">
<thead>
<tr>
<th class="col col-1">Symbol</th>
<th class="col col-2">Name</th>
<th class="col col-3">Total Shares</th>
<th class="col col-4">Purchase Price</th>
<th class="col col-5">Current Price</th>
<th class="col col-6">Percent Change</th>
<th class="col col-7">Profit/Loss</th>
<th class="col col-8">Total</th>
</tr>
</thead>
{% for stock in stocks %}
<tbody>
<tr>
<td>{{ stock["symbol"] }}</td>
<td>{{ stock["name"] }}</td>
<td>{{ stock["sumshares"] }}</td>
<td>{{ stock["purchase_p"] | usd }}</td>
<td>{{ stock['ap'] | usd }}</td>
<td id="Perc_change">{{ stock['perc_change'] }}</td>
<td id="prolos">{{ stock['prolos'] | usd }}</td>
<td>{{ stock['total'] | usd }}</td>
</tr>
</tbody>
{% endfor %}
</table>
<div align="right" style=padding-bottom:20px>
<h4>Cash: {{ availableCash | usd }}</h4>
</div>
<div align="right">
<h4>Total Value: {{ grandTotal | usd }}</h4>
</div>
<script>
document.addEventListener("DOMContentLoaded", function(){
var value=document.getElementById('Perc_change').innerHTML;
if (value>0) {
document.getElementById('Perc_change').style.color="green";
document.getElementById('Perc_change').innerHTML += "%";
document.getElementById('Perc_change').innerHTML += "&#x25B2";
document.getElementById('prolos').style.color="green";
}
if(value<0) {
document.getElementById('Perc_change').style.color="red";
document.getElementById('Perc_change').innerHTML += "%";
document.getElementById('Perc_change').innerHTML += "&#x25BC";
document.getElementById('prolos').style.color="red";
}
});
</script>
{% endblock %}
What I am trying to do is to write a for loop that will go over each row (could be many stocks in Index) and execute the JS written below. (note: I have removed the for loop I had as it did not work) the current script is working where there is only one row in the Index.
Solved it by using Jinja so if anyone will be of interest this what I have done:
{% extends "layout.html" %}
{% block title %}
Index
{% endblock %}
{% block main %}
<div>
<table class="table table-striped">
<thead>
<tr>
<th>Symbol</th>
<th>Name</th>
<th>Total Shares</th>
<th>Purchase Price</th>
<th>Current Price</th>
<th>Percent Change</th>
<th>Profit/Loss</th>
<th>Total</th>
</tr>
</thead>
{% for stock in stocks %}
<tbody>
<tr>
<td>{{ stock["symbol"] }}</td>
<td>{{ stock["name"] }}</td>
<td>{{ stock["sumshares"] }}</td>
<td>{{ stock["purchase_p"] | usd }}</td>
<td>{{ stock['ap'] | usd }}</td>
{% if stock['perc_change'] > 0 %}
<td style="color:green;">▲{{ stock['perc_change'] }}%</td>
<td style="color:green;">{{ stock['prolos'] | usd }}</td>
{% elif stock['perc_change'] < 0 %}
<td style="color:red;">▼{{ stock['perc_change'] }}%</td>
<td style="color:red;">{{ stock['prolos'] | usd }}</td>
{% else %}
<td style="color:gray;">{{ stock['perc_change'] }}%</td>
<td style="color:gray;">{{ 0.00 | usd }}</td>
{% endif %}
<td>{{ stock['total'] | usd }}</td>
</tr>
</tbody>
{% endfor %}
</table>
<div style=padding-bottom:20px>
<h4>Cash: {{ availableCash | usd }}</h4>
</div>
<div style=padding-bottom:20px>
<h4>Total Value: {{ grandTotal | usd }}</h4>
</div>
<div>
{% if totalprolos > 0 %}
<h4 class="inline">Total Profit/Loss:</h4>
<h4 class="inline" style="color:green;">▲{{ totalprolos | usd }}</h4>
{% elif totalprolos < 0 %}
<h4 class="inline">Total Profit/Loss:</h4>
<h4 class="inline" style="color:red;">▼{{ totalprolos | usd }}</h4>
{% else %}
<h4 class="inline">Total Profit/Loss:</h4>
<h4 class="inline" style="color:gray;">{{ totalprolos | usd }}</h4>
{% endif %}
</div>
{% endblock %}
This will show on the table of stocks an arrow up and the percent change if the stock went up, and red if down. JS wasn't needed as Jinja has a more straightforward solution.

The lines breaks in my rows when viewing in PDF. (When adding minus symbol)

I have a problem when i View my html page in PDF-form. The problem is that when the number values are to big then it breaks the line between the minus symbol and values.
Here is an example of the hmtl page, it works perfect
enter image description here
Then when i convert it to a PDF it looks like this:
enter image description here
Here i Render my page to a full html document:
def document_to_html_document(document):
"""
Renders the invoice to a full html document with <html>, <head>, and <body> tags.
"""
return render_to_string('invoice_print.html', {
'body': document_to_html(document),
'document': document,
'base_url': settings.SITE_BASE_URL
})
The code where i build the HTML string and converting it to a pdf:
def document_to_pdf(document, server_base_url, target=None):
# Build HTML string
html = document_to_html_document(document)
# Setup input and output files
html_file = tempfile.NamedTemporaryFile(suffix='.html')
html_file.write(document_to_html_document(document).encode())
target = target or tempfile.NamedTemporaryFile()
# Convert to pdf
command = 'xvfb-run wkhtmltopdf --footer-right "[page]/[topage]"{s} {o}'.format(
s=html_file.name,
o=target.name
)
s = subprocess.Popen(command, shell=True)
s.communicate()
# Return pdf bytes
target.seek(0)
return target.read()
This is my hmtl code where i add the "body":
<html>
<head>
<title>MOSEK-{{ document }}</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<!-- JQuery -->
<script src="{{ base_url }}static/assets/vendor/jquery-1.11.1.js"></script>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="{{ base_url }}static/assets/vendor/bootstrap-3.1.1-dist/css/bootstrap.min.css">
<!-- Optional theme -->
<link rel="stylesheet" href="{{ base_url }}static/assets/vendor/bootstrap-3.1.1-dist/css/bootstrap-theme.css">
<!-- Latest compiled and minified JavaScript -->
<script src="{{ base_url }}static/assets/vendor/bootstrap-3.1.1-dist/js/bootstrap.min.js"></script>
<style>
body {
width: 950px;
}
</style>
</head>
<body>
<div>
<div class="container">
{{ body|safe }}
</div>
</div>
</body>
I have no idea how to solve it, any help would be appreciated :)
This is the content of the Invoice_body:
<div class="row">
<div class="col-xs-12">
<table class="invoice-lines">
<thead>
<tr class="underline overline">
<th>No.</th>
<th>Part ID / Description</th>
<th class="nowrap fr sec-column">Quantity</th>
<th class="nowrap fr sec-column">List price</th>
<th class="nowrap fr sec-column">Unit price</th>
<th class="nowrap fr sec-column">Total</th>
</tr>
</thead>
<tbody>
{# We want the border-bottom of the last line to be darker. #}
{# In order to find this last line, we first need to determine #}
{# if there are custom items. If there are, then the last line #}
{# will be a custom item, since they are printed last. If not, #}
{# then we need to find the last product line. #}
{% for line in lines %}
{% with lines|next:forloop.counter0 as next_line %}
<tr class="line{% if not citems and not next_line %} last-line{% endif %}">
<td>{{ line.line }}</td>
<td>
{% if line.objs.0.product.name %}
{{ line.objs.0.product.name }}<br />
{% else %}
{{ line.objs.0.serial.product.name }}-{% if line.objs.0.back == 1 %}BACK{% endif %}MAIN<br />
{% endif %}
{% if line.objs.0.back and line.objs.0.back_description != '' %}
{{ line.objs.0.back_description }}<br />
{% elif line.objs.0.back == False and line.objs.0.description != '' %}
{{ line.objs.0.description }}<br />
{% else %}
{{ line.objs.0.description }}<br />
{% endif %}
{% if line.objs.0.start %}
Period: {{ line.objs.0.start }} - {{ line.objs.0.end }}<br />
{% endif %}
Serial(s): {{ line.list }}
</td>
<td class="nowrap fr sec-column">{{ line.qty }}</td>
<td class="nowrap fr sec-column">{{ line.objs.0.price|floatformat:2 }}</td>
<td class="nowrap fr sec-column">
{{ line.objs.0.subtotal|floatformat:2 }}
{% if line.discount %}<br>({{ line.discount }}% dis.){% endif %}
</td>
<td class="nowrap fr sec-column">{{ line.rowtotal|floatformat:2 }}</td>
</tr>
{% endwith %}
{% endfor %}
{% for citem in citems %}
{% with citems|next:forloop.counter0 as next_citem %}
<tr class="line{% if not next_citem %} last-line{% endif %}">
<td>{{ citem.line }}</td>
<td>
{{ citem.obj.name }}
{% if citem.obj.agreement %}
<br>Agreement: {{ citem.obj.agreement }}
{% endif %}
</td>
<td class="sec-column"> </td>
<td class="fr sec-column">{{ citem.rowtotal|floatformat:2 }}</td>
<td class="fr sec-column">{{ citem.rowtotal|floatformat:2 }}</td>
<td class="fr sec-column">{{ citem.rowtotal|floatformat:2 }}</td>
</tr>
{% endwith %}
{% endfor %}
<tr class="sum-line" id="subtotal-line">
<th colspan="4" class="fr">Subtotal</th>
<th> </th>
<td class="fr sec-column">{{ inv.subtotal|floatformat:2 }}</td>
</tr>
{% for vat, lines, message, total, rate in vats %}
<tr class="sum-line">
<td colspan="4" class="fr">
<span class="nowrap">Line {{ lines }} : </span>
{{ message }}
<span class="nowrap"> ({{ rate }}% VAT)</span>
</td>
<td class="fr sec-column">{{ total }}</td>
<th> </th>
</tr>
{% endfor %}
<tr class="sum-line">
<th colspan="4" class="fr">VAT total</th>
<th> </th>
<td class="fr sec-column">{{ inv.vat|floatformat:2 }}</td>
</tr>
<tr class="sum-line">
<th colspan="4" class="fr">Total ({{ inv.currency }})</th>
<th> </th>
<td class="fr grand-total overline sec-column">{{ inv.total|floatformat:2 }}</td>
</tr>
</tbody>
</table>
</div>
</div>
add the flag zoom to the export command:
command= xvfb-run wkhtmltopdf --zoom 1.5 --footer-right
The solution from Eliethesaiyan:
in the command= xvfb-run wkhtmltopdf --zoom 1.5 --footer-right

select child element jQuery

I have a table structured like this:
<table>
<tbody>
for loop here
<tr>
<td>Item X Attribute 1</td>
<td>Item X Attribute 2</td>
<td><button name="test" onclick="display_variants()">Hide my kids</button></td>
</tr>
<tr>
<tbody class="variants_info">
<tr>
<td>Item X Variant 1</td>
<td>Item X Variant 2</td>
</tr>
</tbody>
</tr>
endfor loop
</tbody>
</table>
So that structure repeats Y amount of times.
I'm trying to make a script that hides the tbody.variants of the row selected.
What I have so far is this:
<script>
function display_variant(){
if($('.variants_info').is(":visible")){
$('.variants_info').hide();
}
else{
$('.variants_info').show();
}
}
</script>
but this hides the variants from ALL the rows.
Is there a way to select the childs of the specific row? Also how can I start with the tbody.variants hidden? (Start as in when I visit the page).
Edit: At the moment is looking closely to this:
Update:
I've managed to change the structure to this:
<table>
for loop
<tbody>
<tr>
<td>image for el 1</td>
<td>attr for el 1</td>
<td><button type='button' name='test'>Click Me</button></td>
</tr>
for loop
<tr class='variants_info'>
<td>variant1 for el 1</td>
<td>variant2 for el 1</td>
</tr>
endfor
</tbody>
endfor
</table>
Update 2: The actual code is this one:
<table class="pure-table pure-table-bordered">
<tbody>
{% for product in collection.products %}
{% if product.available %}
<tr class="{% cycle 'pure-table-odd', '' %}">
<td>
<img src="{{ product.featured_image.src | product_img_url: 'thumb' }}" alt="{{ product.featured_image.alt | escape }}" />
</td>
<td>{{ product.title }}</td>
<td style="text-align:right">
<button type="button" name="click_me">Click Me</button>
</td>
</tr>
{% for variant in product.variants %}
<tr>
<td>{{variant.title}}</td>
<td>{{variant.price | money }}</td>
</tr>
{% endfor %}
{% endif %}
{% endfor %}
</tbody>
</table>
<script>
$("td button").click(function(){
$(this).closest('tr').next().toggle();
})
</script>
I still can't get the JS to work.. =/ Current one is only hiding the first variant( Instead of all the variants for the clicked button )
I would suggest to mark the rows that contain the products with a class name, e.g. "product", like this:
<tr class="product {% cycle 'pure-table-odd', '' %}">
<td>
<img src="{{ product.featured_image.src | product_img_url: 'thumb' }}"
alt="{{ product.featured_image.alt | escape }}" />
</td>
<td>{{ product.title }}</td>
<td style="text-align:right">
<button type="button" name="click_me">Click Me</button>
</td>
</tr>
You would not add that class to the rows that have the variants.
Then in your JavaScript use the nextUntil method to match all next variant rows (which do not have the "product" class) until, but excluding, the next product row, and apply the toggle() method to all these:
$("td button").click(function(){
$(this).closest('tr').nextUntil('.product').toggle();
});
Alternative structure 1
Instead of a single table, you could create nested tables, one for each product, containing the variants. It would look somewhat like this:
<table class="pure-table pure-table-bordered">
<tbody>
{% for product in collection.products %}
{% if product.available %}
<tr class="{% cycle 'pure-table-odd', '' %}">
<td>
<img src="{{ product.featured_image.src | product_img_url: 'thumb' }}"
alt="{{ product.featured_image.alt | escape }}" />
</td>
<td>{{ product.title }}</td>
<td style="text-align:right">
<button type="button" name="click_me">Click Me</button>
</td>
</tr>
<tr>
<table class="some other class specific for variants">
<tbody>
{% for variant in product.variants %}
<tr>
<td>{{variant.title}}</td>
<td>{{variant.price | money }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
This has advantages and disadvantages. The main disadvantage is that the columns of these sub-tables are not aligned with the columns in the main table. But it depends on what you want...
The JavaScript code would then have to be like you had it originally:
$("td button").click(function(){
$(this).closest('tr').next().toggle();
});
Alternative structure 2
You could also wrap each "section" (consisting of one product row and the variant rows that belong to it) with a tbody tag. Although not commonly done, this is allowed as stated on MDN:
Note that unlike the <thead>, <tfoot>, and <caption> elements however, multiple <tbody> elements are permitted (if consecutive), allowing the data-rows in long tables to be divided into different sections, each separately formatted as needed.
This is different from your original HTML, where you had tbody elements as children of tr elements, which is invalid HTML.
It would look like this:
<table class="pure-table pure-table-bordered">
{% for product in collection.products %}
{% if product.available %}
<tbody>
<tr class="{% cycle 'pure-table-odd', '' %}">
<td>
<img src="{{ product.featured_image.src | product_img_url: 'thumb' }}"
alt="{{ product.featured_image.alt | escape }}" />
</td>
<td>{{ product.title }}</td>
<td style="text-align:right">
<button type="button" name="click_me">Click Me</button>
</td>
</tr>
{% for variant in product.variants %}
<tr>
<td>{{variant.title}}</td>
<td>{{variant.price | money }}</td>
</tr>
{% endfor %}
</tbody>
{% endif %}
{% endfor %}
</table>
You can then use the nextAll() method to hide the variant rows, because they are delimited by the tbody wrapper from the next product row:
$("td button").click(function(){
$(this).closest('tr').nextAll().toggle();
});
Initially hiding the variant rows
If you want the variants all to be hidden at first, then add the following attribute to those rows in the HTML code:
<tr style="display:hidden">
You would of course not do this for the product rows. Also, you might want to define a CSS class for this (e.g. tr.hidden { display:hidden; } instead of using style.
The jQuery toggle() method will override this style when showing, and restore it again when hiding.
Your HTML is not valid so you can change that and then use this DEMO
$("td button").click(function() {
$(this).closest('tr').next().toggle();
})
try this one :-
$("td button").click(function() {
$(this).closest('tr').nextUntil("tbody").toggle();
});
the jsfiddle demo link is :- https://jsfiddle.net/Lg0wyt9u/776/

for loop swig, nodejs

i'm trying to create a loop..
here's the javascript:
for (var j = 0; j < b; j++) {
if(j%4 == 0 && j != 0){
newTable.appendChild(tr);
tr = document.createElement('tr');
}
i want max 4 cells each rows, so if i have 9 cells, i should have 2 full rows and 1 row with only one cell.
how do we set a condition with swig like javascript?
here's my html code:
<table id="asdf">
<tbody>
{% if styles in styles.length %}
<tr>
{% for style in styles %}
<td>
<table border="1">
<tbody>
<tr><td><div style="width: 175px;height: 250px" id="products"><img id="img" src="{{style.img}}" ></div></td></tr>
<tr><td id="styleno">{{style.style}}</td></tr>
</tbody>
</table>
</td>{% endfor %}
</tr> {% endif %}
</tbody>
</table>
</div>
{% for style in styles %}
{% if loop.index0 % 4 === 0 && loop.index0 !== 0 %}
<tr>
{% endif %}
<td>
<table border="1">
<tbody>
<tr>
<td><div style="width: 175px;height: 250px" id="products"><img id="img" src="{{style.img}}" ></div></td></tr>
<tr><td id="styleno">{{style.style}}</td></tr>
</tbody>
</table>
</td>
{% endfor %}

Categories

Resources