How to include properly Javascript using a Javascript Twig Template - javascript

I know how to access my assets, but i wanted to create a template working with Javascript and Twig, which would allow me to use Twig variables in my script.
For example, I have a template called 'details.html.twig', which extends a 'layout.html.twig':
{% extends '#AcmeBundle/Front/layout.html.twig %}
{# SOME CODE AND CONTENT #}
{% block page_script %}
{{ parent() }}
<script>
{# Part of my script #}
</script>
{% endblock page_script %}
All of this worked perfectly, but to be able to reuse some js code (using twig variables), I cut some part of my script and put I in an external template, called 'viewer.html.twig'. To be able to use it in my 'details.html.twig', I used:
{% include '#AcmeBundle/Front/Model/viewer.html.twig' %}
I put this line right after the {{ parent() }} one and before the <script> tag.
However, my script which used to work when directly written in 'details' template seems to be quite ignored right now.
If any of you could have a clue of what makes my template being included but skipped, or a way to include the template easier or properly, I'm open to all kind of observations.
G'day,
Jérémy

If you code a file containing only javascript you should name your file:
{% include '#AcmeBundle/Front/Model/viewer.js.twig' %}
Then Twig (as of 1.17) automatically defines its escaping strategy based on the extension.
See the twig docs and an example of js twig file in symfony.

Related

About using jinja templating in JS file

I have been using a template in which there's images of previous and next button is in JavaScript file. The Framework I'm using is Django, is there any solution to use jinja templating/rendering for these images in JS file.
JS code:
$(".active-banner-slider").owlCarousel({
items:1,
autoplay:false,
autoplayTimeout: 5000,
loop:true,
nav:true,
navText:["<img src={% static 'img/banner/prev.png' >","<img src={% static 'img/banner/next.png' %}>"],
dots:false
});
I used same static method with html files and it worked, I don't know if this method does even work with JS file or not? if it does what would be the correct way?
Yes, you can generate a JS component of a web page using the Django template processor, or Jinja if you prefer. You do, however, need to make sure that the JS is generated in the correct context (surrounded by appropriate tags, in the right place in your rendered output). You also have to be careful to code your JS using { { and } } (significant spaces!) never {{.
If you use "view page source" and your browser's debugging tools, you will probably spot what you are doing wrong.
My site base template has a block onready_js like this:
<script type="text/javascript"> $(document).ready( function() {
{% block onready_js %}{% endblock onready_js %}
});
</script>
into which you can inject bits of JS to be executed when the page becomes ready, like this (ignore the irrelevant details, apart from the use of {{...}} and {% if ... %} etc. Absent any block definition, the base template generates a null $(document).ready( function() { });
{% block onready_js %}
{% if form or POST_name %}
// activate the button column to POST to this target with this name
var buttons = $('button.MyFilterSelectButton');
buttons.attr('type','submit').attr('name','{{POST_name}}')
buttons.click( function(event){
$('#id_{{POST_name}}').val( $(this).attr('value') );
/* stuff deleted */
$('.MyFilterSelectCol').show();
{% else %}
// hide the button column which doesn't do anything useful
$('.MyFilterSelectCol').hide();
{% endif %}
{% endblock onready_js %}

Can I use liquid inside JS file?

I'm using Shopify and I need to show some message if specific product tag is exist. I need to check for product tags from JS file and need to know how can I do that.
I tried to use {{product.tags}} in the js file but I got an error, I also tried that in .js.liquid file and it still throw an error.
{% assign clearance = false %}
{% for tag in product.tags %}
{% if tag contains 'Clearance' %}
{% assign clearance = true %}
{% endif %}
{% endfor %}
There is a way that I could use that in js? If not, how can I grab all product tags in js way? I know I can do that from liquid file but I have to do that only in the js file.
You are probably looking for an extension to Javascript called jsx.
Aside from that, natively, you have template literals, but you can only use expressions in that, no looping or other logic (aside from ternary expressions).
If what you are looking for is not related to creating HTML, but only to modifying a variable (or executing other code on data), you can use standard Javascript:
let clearance = false;
for (const tag in product.tags) { // this assumes product.tags is an object
for (const tag of product.tags) { // this assumes product.tags is an array
if (tag.includes('Clearance') {
clearance = true;
}
}
The .js.liquid file will only accept translation string as var in Liquid (example: {{ "my_text" | t }}.
If you want to use other kind of Liquid strings in Javascript code, you may use a section and include your javascript inside {% javascript %} tags.
This will also work in a snippet or a template.

Flask - Component templates structure?

I've been experimenting with a Flask template structure to resemble a component workflow. This is inspired by Vue.
Some key ideas :
Each page is treated as a component
A component is just a folder containing all necessary files inside it (except ones that are common)
Each component is encourageg to have several HTML files to avoid large files, we will be using Jinja's include to "bundle" them
togheter
Avoid javascript, or at least, loading unnecessary javascript, each page will include only what's necessary
Here's an example :
The route for PageExample would be the following :
app.route('/example'):
return render_template('PageExample/html.html')
And PageExample/html.html :
{% extends 'base.html' %}
{% block content %}
<div class="tab" id="tab1">
{% include 'PageExample/tab1.html' %}
</div>
<div class="tab" id="tab2">
{% include 'PageExample/tab2.html' %}
</div>
{% endblock %}
PageExample/tab1.html (tab2 follows the same logic)
<!-- block header is in base.html -->
{% block header %}
{{ super() }}
<script src="{{url_for('components', 'PageExample/tab1.js')}}">
{% endblock %}
<div class="tab-content">
Some content here that uses the tab1.js javascript
</div>
So, what's the question ?
I have limited experience with Flask, so I'm not sure if this idea is sound, it seems hacky but it makes developing pages easier, especially with multiple people (the little javascript a page might need can be done in any way). Also increased loading speed by a ton.
Dos this work? Is this structure reccomended? Are there any flaws to it? What sort of problems could I run into? Any recommendation to do it better? Is this already done nowadays in Flask? I couldn't find any examples of a Flask app done this way (specially the Jinja stuff using lots of includes)
I'm currently not at my main computer, so I'll update this later if need be, but if your included html files referenced any data that is stored in the backend then you'd also need to make sure you reference the exact location there as well.
For example:
If you need the first name property from a User class it would be
{{ User.firstName }}
Not only that, but the tab template will also need to be supplied this User.firstName variable, which isn't done implicitly.
You will need to create what is called a Blueprint then a View and tell the view to make the User.firstName variable available to PageExample/tab1.html
tabs.py
import User
from flask import Blueprint, render_template
import """other flask dependencies needed"""
bp = Blueprint('index', __name__, url_prefix='/')
def tabData():
"""data to process"""
render_template("PageExample/tab1.html", User=User)
In that same tabs.py file, you can also write a view for tab2.html as well as html.html. Should be noted that I'm assuming that the contents of PageExample are for the index of the website and that they will all be rendered on that same page.
Also, It seems like your tabs will be in the content/body of the html but it will also render the blocks of base.html and add the defined scripts inline with the body of html.html. Instead, it should be referenced in the html.html file itself
html.html
{% extends 'base.html' %}
{% block header %}
{{ super() }}
<script src="{{url_for('components', 'PageExample/tab1.js')}}">
{% endblock %}
{% block content %}
<div class="tab" id="tab1">
{% include 'PageExample/tab1.html' %}
</div>
<div class="tab" id="tab2">
{% include 'PageExample/tab2.html' %}
</div>
{% endblock %}
with tab1.html being
<div class="tab-content">
Some content here that uses the tab1.js javascript
</div>
Obviously, this is just the surface of what you will need to know about flask. Think the bottom line is that it can work. Although I would suggest that your put all resources such as JS and CSS in a separate folder and reference those resources from those locations.
For more information on Flask and how you can utilise it, check out the Flask Tutorial here:
http://flask.pocoo.org/docs/1.0/tutorial/

Shopify - using if statements within js.liquid and scss.liquid files

I am trying to merge JS files together in 1 file, however I need to set conditions using the if statements within the js file.
I have created file.js.liquid but it does not seem to working; I added a test for example:
{% if template contains 'index' %}
console.log('homepage loaded');
{% endif %}
Example of what i am trying to do, of course have plenty i need to do.
{% if settings.the_simpsons_enabled and settings.simpsons_video_enable %}
// video popup
$(".video-popup").videoPopup();
{% endif %}
The conditional statements are also not working within scss.liquid files either:
{% if template contains 'index' or template contains 'collection' or template contains 'product' %}
#import url("{{ 'owl.carousel.scss' | asset_url }}");
{% endif %}
Any ideas why if would not be working or if its even possible? I assume it is being a liquid file.
The Liquid extension on such files like CSS or JS allows use of Liquid variables but not statements.
So {{ write_my_liquid_var_here }} will work. {% if liquid_statement %}do something{% endif %} won't.
Regarding Shopify and SASS
The following won't work as you can't use #import in Shopify's SASS files.
#import url("{{ 'owl.carousel.scss' | asset_url }}"); //This will not work
Regarding using conditional liquid statements in .js.liquid files
I don't know everything about this subject, but I do know the following two things.
1) Check out this thread and you'll see that this type of statement won't work because js files are parsed independent of normal liquid templates, so it would have no idea which template you're viewing.
{% if template contains 'index' %} //This will not work
A better place to put the above logic would be at the bottom of your theme.liquid file above the </body> tag. However this won't help you with what seems to be your goal of reducing HTTP requests by using one JavaScript fie.
2) However, you can access values in your settings_data.json file
{% if settings.the_simpsons_enabled and settings.simpsons_video_enable %} //This will work
I hope this helps

How to load a custom JS file in Django admin home?

I have a heavily customized Django admin where it's very simple to load a custom JS file for each of my ModelAdmins:
class MyModelAdmin(admin.ModelAdmin):
class Media:
js = ('js/admin/mymodel.js',)
But how do I do this for the admin "homepage," where all my admin models are listed?
Update #1: amending my question, since the solutions below aren't that useful if I cannot efficiently include Django's jQuery. So, how do I include Django's jQuery in the JS file? If I wrap my code with (as I do in my other ModelAdmin JS files):
(function ($) {
// my code here...
})(django.jQuery);
I get the following error:
ReferenceError: django is not defined.
Thanks.
Update #2: I was able to include Django's jQuery successfully by following this answer: https://stackoverflow.com/a/10584539/585783
You can override templates/admin/index.html and add the JavaScript in the block extrahead:
{% extends "admin/index.html" %}
{% block extrahead %}
{{ block.super }}
# add a <script> tag here with your JavaScript
{% endblock %}

Categories

Resources