building a array/object in a nunjucks loops - javascript

I have the following in my nunjucks file,
{% set inProgressJobs = [] %}
{% for job in jobs %}
{% set inProgressJobs = (setProgressJobs.push([
{
text: "<b>{{ job.jobTitle}}</b>"
}
]), inProgressJobs) %}
When I use this in by view I would expect to see Web Designer but I am actually seeing {{ job.jobTitle }} how I interprolate my var into the text attribute?

You try to coding inside a template. It's a possible (see below) but out of template ideology. Try to put necessary logic to filters and global functions.
const nunjucks = require('nunjucks');
const env = nunjucks.configure();
env.addFilter('print', console.log); // for debug
const html = env.renderString(`
{% set arr = [] %}
{% for i in range(1, 10) %}
{{ '' if arr.push(i) }} {# arr.push always returns non-zero so result will be '' #}
{% endfor %}
{{ arr | print }} {# print arr to console #}
`);
// console.log(html); // html is a pack of spaces and tabs

Related

Passing data attributes from Shopify Schema blocks to JS

I'd like to pass data from the following schema setting to JS. Multi-word strings will be input in the editor. Using a slick slider, the user should be able to click through the quotes and see the current quote. However, when the quotes show up, only the first word of the string is displayed. For example: if the string "New York Times" is entered in the editor, only "New" is displayed". How can I fix my code so that the whole string is passed to JS?
In the liquid file I have the following:
<li class="press-slider-item" data-quote={{block.settings.quote}} {{ block.shopify_attributes }}>
...
{
"type": "textarea",
"id": "quote",
"label": "Featured Quote"
}
I attempted to access the data values by doing the following in JS:
var quoteList = [];
$(document).ready(()=>{
const slides = document.querySelectorAll('.press-slider-item');
slides.forEach(slide=>quoteList.push(slide.dataset.quote));
...
Then the Slick afterChange event is defined:
$('.press-slider').on('afterChange', function(event, slick, currentSlide, nextSlide){
const featQuote = document.getElementById('press-featured-quote');
if(currentSlide + 1 == quoteList.length){
console.log(quoteList[0]);
featQuote.innerHTML = quoteList[0];
}else{
console.log(quoteList[currentSlide+1]);
featQuote.innerHTML = quoteList[currentSlide+1];
}
});
I figured it out using inline scripts. Here's my solution. Not sure if this is the best way to do this, but it works for what I need.
<script>var quoteList = [];</script>
<ul class="press-slider">
{% for block in section.blocks %}
<li class="press-slider-item"{{ block.shopify_attributes }}>
<script>quoteList.push(`{{block.settings.quote}}`)</script>
{% if block.settings.link != blank %}
<a href="{{ block.settings.link }}" class="logo-bar__link">
{% endif %}
{% if block.settings.image != blank %}
{{ block.settings.image | img_url: '160x160', scale: 2 | img_tag: block.settings.image.alt, 'logo-bar__image' }}
{% else %}
{{ 'logo' | placeholder_svg_tag: 'placeholder-svg' }}
{% endif %}
{% if block.settings.link != blank %}
</a>
{% endif %}
</li>
{% endfor %}
</ul>
<script>
$('.press-slider').on('afterChange', function(event, slick, currentSlide, nextSlide){
const mediaQuery = window.matchMedia('(min-width: 481px)');
// Check if the media query is true
if (mediaQuery.matches) {
const featQuote = document.getElementById('press-featured-quote');
if(currentSlide + 1 == quoteList.length){
featQuote.innerHTML = quoteList[0];
}else{
featQuote.innerHTML = quoteList[currentSlide+1];
}
}
});
</script>

'first_time_accessed' Shopify liquid variable is always false

I'm trying to use the first_time_accessed liquid variable in my checkout.liquid Shopify template to decide whether or not to push certain data to an array, like so:
config.elements.push({
id: prodId,
price: prodPrice,
quantity: prodQty,
{% if first_time_accessed %}
{% assign last_purchase_date = "January 1, 1970" %}
{% for order in customer.orders %}
{% if (order.order_number != checkout.order.order_number) and (order.created_at > last_purchase_date) %}
{% assign last_purchase_date = order.created_at %}
{% endif %}
{% endfor %}
{% assign raw_new_customer_boundary = 'now' | date: "%s" | minus : 46656000 /* 540 days */ %}
{% assign raw_last_purchase_date = last_purchase_date | date: "%s" | minus: 0 %}
new_customer: {% if raw_new_customer_boundary > raw_last_purchase_date %}true{% else %}false{% endif %},
{% endif %}
});
However, every time I test this code I can see that first_time_accessed is always false. I've also tested this by putting similar code on other pages and it always equates to false. I've tested it in incognito mode with a VPN and same thing.
I'm wondering if anyone has any idea why first_time_accessed is always false? I'm sure it has to do with some misunderstanding on my end about how this variable works, but there's very little info on Shopify's docs about it.

How do i create and use variables in django

New to Django and its templates.
I'm trying to set a variable given a specific situation, and that part I think ill be able to do, the code below isn't the exact conditions its just there as a demo. The part im stuck on is how do i create a variable name, and then use that name variable elsewhere. Such as within a div or within a method or anywhere else within the html file, and withing different <Script> tags to run methods and for really any purpose.
demo scenario :
{% for row in table.rows %}
{% if row == 2 %}
{% var name = row.name %}
{% endif %}
{% endfor %}
{% if name %}
<div>{{name}}</div>
{% endif %}
my actual code Im trying to implement:
<script type="text/javascript">
function map_init_basic(map, options) {
var markerClusters = L.markerClusterGroup({ chunkedLoading: true });
{% for row in table.rows %}
var x = "{{ row.cells.x }}"
var y = {{ row.cells.y }}
var m = L.marker([y, x])
m.bindPopup("{{row.cells.first_name}} {{row.cells.last_name}} <br>{{row.cells.chgd_add}}");
m.on("click" , ()=>{
//console.log(`${first_name} ${last_name}`)
{% var first_name = {{row.cells.first_name}} %}
})
//changed row.cells.chgd_add to row.cells.Chgd_add to make sure its matching the table
markerClusters.addLayer(m);
{% endfor %}
markerClusters.addTo(map);
}
{% if first_name %}
console.log("{{first_name}}");
{% endif %}
</script>
Django templates are intended to render html but you are trying to render javascript. It can work but the way you are trying to do it is not a good practice; very soon you won't be able to maintain your code.
If you want to pass data directly from python/django to javascript, an accceptable way to do so is to put the data in a dictionary, translate it to a json string and have it set to a var in your javascript.
in a view:
data = dumps(some_dictionary)
return render(request, 'main/template.html', {'data': data})
in the template:
<script>
var data = JSON.parse("{{data|escapejs}}");
</script>
https://docs.djangoproject.com/fr/3.1/ref/templates/builtins/#escapejs
Alternative: You can use django to generate a widget with data attributes and have a javascript operating on this widget and do whaterever needs to be done.

Adding python variables to jinja counter

I want to add the python variables from flask in the jinja template
Suppose 'a' is a python variable(a list of int values) brought into the jinja template using render_template function from flask :
{%set count = 0%}
{%for element in a%}
{%set count = count + element%}
{%endfor%}
{{ count }}
The value of 'count' should be updated but it still prints 0 on the screen
Can anyone help me?
In the most recent versions, due to scoping rules, your version doesn't work.
Instead, you could do something like this:
{% set count = namespace(value=0) %}
{% for element in a %}
{% set count.value = count.value + 1 %}
{% endfor %}
{{ count }}

How to set an item to be the first in a for loop in Liquid if a condition is met

I have a for loop in Liquid which loops through customer addresses. What I would like to do is make the address which has been set as the default (customer.default_address) as the first address to appear in the loop. I currently add a default tag to the default address but struggling to make it the first to appear.
I tried using 'sort' but with no luck.
My current code is below.
Any help would be much appreciated.
{% assign sortedAddresses = customer.addresses | sort: 'customer.default_address' %}
{% for address in sortedAddresses %}
<div class="address">
{{ address | format_address }}
{% if address == customer.default_address %}
<div class="default">DEFAULT</div>
{% endif %}
</div>
{% endfor %}
You have default_address as a property of customer and Im guessing customer.addresses is an array of strings. If you were to make customer.addresses an array of objects instead... with string property for address and true/false property for default, then you could do something like:
{% assign default_address = customer.addresses | where: "default", true %}
{% assign address_array = default_address | concat: customer.addresses %}
{% assign customer.addresses = address_array | uniq %}

Categories

Resources