Create variable in Django template - javascript

I have this in my template:
{% for category in menu_categories %}
{% with menu_button = "menu_"{{category}} %}
<button class="button {{menu_button}}" onclick="showItem(menu_button)">{{category}}</button>
{% endwith %}
{% endfor %}
I am trying to create a series of buttons with class name by iterating a queryset of model categories.
I create a variable menu_button so that I could systematically name them, and pass the name to a JavaScript function showItem().
But I get the error 'with' expected at least one variable assignment. What am I doing wrong? Thanks.

Related

HTML if else condition for printing items in list

I'm making a website with flask, and I pass in a list. My .html file has this code:
{$ for file in list %}
<div>
<img ... > </img>
</div>
{% endfor %}
Now if list.length == 0 I want it to just do something like
<h2> Error </h2>
instead. How do I make an if statement to check if the list is empty, and if it is then I print error on the website, if it is not, I print the images in the list. I tried to put:
<script>
if(list.length==0){
<h2>Error</h2>
}
else{
"the for loop stuff"
}
</script>
but this does not work.
THanks
In Flask with Jinja2 as a template engine, the if-else syntax requires you to write the following statement
{% if mylist.length == 0 %}
<div>error</div>
{% else %}
<!-- loop -->
{% endif %}
Note: Since list is a Python keyword i suggest you to use another name for your list in order to avoid possible conflicts.
In this pythonprogramming page about flask 7, you will find some example code and a video. The example shows an if-else statement:
{% for post in posts %}
<h3> {{ post.title }}</h3>
<p>{{ post.body }}</p>
{% if author %}
<span style="font-size:0.5em;color:yellowgreen">{{ post.author }} </span>
{% endif %}
{% if date %}
<span style="font-size:0.5em;color:yellowgreen">{{ post.date }}</span>
{% endif %}
{% endfor %}
I decided to post my answer to share this learning resource because I have noted that the example does not use any <script> tag (not sure if it helps).
The comparison operator is almost the same everywhere as you can see in both the Python and Jinja references.
Therefore, the equivalent for your code would be:
{% if list.length == 0 %}
...
{% endif %}

Print Django model data as JavaScript Array

I have printed a for loop as below in my HTML Template:
<td>
{% for athlete in booking.athlete.all %}
{{athletes.id}}
{% endfor %}
</td>
The Output in HTML is as below.
<td>
1
2
3
</td>
Is it possible to get the output to appear as [ "1", "2", "3" ], so we can then use this as a JS array or object?
I have tried a few things from the Django Template but it does not remove the additional white space.
The easiest way is probably to use a custom template tag to get the list of athlete.ids, and then the built-in json_script filter to render those ids as json.
Let's assume your app name is myapp. If you don't have any custom filters yet, create the directory myapp/templatetags/, and add an empty __init__.py file. Then in the file myapp/templatetags/myapp_filters.py add:
from django import template
register = template.Library()
#register.filter
def qs_to_id_list(qs):
return list(qs.values_list('id', flat=True))
In your template example, you would do:
{% load myapp_filters %}
{% for booking in bookings %}
<tr>
<td>{{booking.id}}</td>
<td>{{booking.program_type}}</td>
<td>{{booking.booking_time}}</td>
{# set a unique script id for easier access in javascript #}
{% with script_id='athletes-data-'|add:booking.id %}
{{booking.athlete.all|qs_to_id_list|json_script:script_id}}
{% endwith %}
</tr>
{% endfor %}
The json_script filter will render a block like this (in each table row):
<script id="athletes-data-5" type="application/json">[1, 2, 3]</script>
which can be accessed in your client-side javascript.

Shopify getJSON('/cart.js') custom values of liquids

Good time of day.
Trying to improve the pop-up cart was stuck on the possibility of using custom values instead of existing ones.
This example works as expected:
$.getJSON('/cart.js').then(
function(cart) {
$('#example').html(theme.Currency.formatMoney(cart.total_price, theme.moneyFormat));
});
In the cart template, I have made other values by liquid codes. Here is an example:
{% for item in cart.items %}
{% assign totalfive = 0 %}
{% assign fiveminus = cart.total_price | times: 0.05 %}
{% assign totalfive = cart.total_price | minus: fiveminus %}
{% endfor %}
In HTML, this value looks like this: <span>{{ totalfive | money }}</span>
The question is about how can I get this value by JSON? Maybe there is a way to catch it with an element based on ID? Or it definitely impossible?

Webpack Encore not loading JavaScript in base template

I am using a Webpack Encore in my Symfony 4 project, and when including the Twig helper for JavaScript in my base.html.twig:
{% block javascripts %}
{{ encore_entry_script_tags('app') }}
{% endblock %}
The JavaScript doesn't load, however, when including the exact same Twig helper in one of my templates (index.html.twig), the JavaScript loads in.
So my question is, why does the above Twig helper work in one of my templates, but not in my base template?
What preciel said is true, using a block inside a template that extends another template will overwrite the default code inside that said block.
However there is another solution than just moving the code outside the block in the base template and that's calling the parent() function
main.twig
{% extends 'base.twig' %}
{% block foo %}
{{ parent() }}
Bar
{% endblock %}
base.twig
{% block foo %}
Foo
{% endblock %}
output
Foo
Bar
demo
It's failing because it's inside your javascript block.
Your template extends base.html.twig, so whatever you place within your javascript block in any template will be inside the javascript block.
But if you do the same within base.html.twig it will just be ignored.
Just move {{ encore_entry_script_tags('app') }} out of your javascript block.
base.html.twig
{{ encore_entry_script_tags('app') }}
{% block javascripts %}
{# nothing here, your templates will overwrite it when you extends base.html.twig #}
{% endblock %}
Remember this: If it's inside your layout, which is base.html.twig, then don't place anything inside the {% block %} tags. It will just be ignored.

If Else Statements, Javascript Toggle, Liquid / Ruby Language

thanks for checking out my question.
The problem I am having is with Shopify, Liquid, JQuery and Javascript.
I have a JQuery / Liquid slider that has four different categories. NBA, NHL, MLB and MLS. When the page loads..
jQuery(document).ready(function ($) {
$(".ncaa-carousel-filter").addClass("active");
$("#ncaa-carousel").toggle();
This makes it so that no matter what section of the site you are on, (NBA, NHL, etc..) you will still see the NCAA carousel until you click on the appropriate toggle.
var carousel = "-carousel";
var carouselFilter = "-carousel-filter";
$("#carousel-filters").on("click", ".ncaa-carousel-filter", function() {
$("[class*="+carouselFilter+"]").removeClass("active");
$(this).addClass("active");
$("[id*="+carousel+"]").hide();
$("#ncaa-carousel").toggle();
});
I have broken out the sliders and trying to use Liquid to display them.
{% if collection.current_type or collection.handle contains "mlb" %}
{% include 'mlb-slider' %}
{% elsif collection.current_type or collection.handle contains "nba" %}
{% include 'nba-slider' %}
{% elsif collection.current_type or collection.handle contains "mls" %}
{% include 'mls-slider' %}
{% elsif collection.current_type or collection.handle contains "nhl" %}
{% include 'nhl-slider' %}
{% else %}
{% include 'ncaa-slider' %}
{% endif %}
I believe the problem is that the sliders are set to display: none until toggled. So when I go to include them, they aren't showing as they are set to display: none.
If I remove that CSS I end up with 4 sliders on my page as they are all showing.
I think this is a question of how I have it set up, I need some help on the logic.
This fiddle shows most of the code I am working with. http://jsfiddle.net/asx90842/
Maybe I can remove the display: none CSS and use the Liquid if statement I've developed in place of the HTML code you see in the fiddle?
Any help would be great!!
Thanks so much!
First, instead of toggling ncaa at page load, why don't you just set it to active in your html templates? Simply put a .active class and in your stylesheets do .active{display:block} or whatever you like. If you can use data-* attributes in your buttons it will be even better since you will not have to use regex to get a corresponding id.
So your html will be like this
<button class="ncaa-carousel-filter active" data-target="ncaa-carousel">College</button>
<div style="margin-bottom:10px;" class="teams-carousel clearfix active" id="ncaa-carousel">
Second, all five carousel button/div all share the same logic so you can just write one listener for all of them:
$("#carousel-filters").on("click", "button", function() {
$("#carousel-filters button").removeClass("active");
$(this).addClass("active");
$(".teams-carousel").hide();
// Use data attributes to get corresponding div id
var id = $(this).data('target');
$(id).toggle();
});
Lastly, I am not very familiar with ruby/liquid but I bet there's a for loop structure that you can use to write just one block and iterate over it with different values.
One way to approach this would be to assign a liquid variable which could be re-used in the Javascript class/id selectors. I would include the following liquid near the top of the page.
{% if collection.current_type or collection.handle contains "mlb" %}
{% assign sport_league 'mlb' %}
{% elsif collection.current_type or collection.handle contains "nba" %}
{% assign sport_league 'nba' %}
{% elsif collection.current_type or collection.handle contains "mls" %}
{% assign sport_league 'mls' %}
{% elsif collection.current_type or collection.handle contains "nhl" %}
{% assign sport_league 'nhl' %}
{% else %}
{% assign sport_league 'ncaa' %}
{% endif %}
With that included, you'll have a new variable, sport_league representing the common string of characters used to represent any particular sport / carousel. For example, you'll now be able to write the following at the end of your Javascript to display just the carousel that's wanted.
$('#{{ sport_league }}-carousel').show();
This is simply javascript that executes once, using the variable sport_league to negate the display: none CSS and show the appropriate carousel.

Categories

Resources