Display JSON data with criteria in Jekyll - json

I have a JSON file with the following structure:
{
"resources": [
{
"date": "Nov 7",
"content": [
{
"articleTitle":"The Distribution of Users’ Computer Skills: Worse Than You Think",
"articleUrl":"https://www.nngroup.com/articles/computer-skill-levels/?ref=boomkrak",
"articleAuthor": "Jakob Nielson",
"articleTag": "ux, web design"
},
{
"articleTitle":"How to Use Animation to Improve UX",
"articleUrl":"https://uxplanet.org/how-to-use-animation-to-improve-ux-338819e93bdb#.84b3m022s?ref=boomkrak",
"articleAuthor": "Nick Babich",
"articleTag": "ux, animation"
}
]
},
{
"date": "Nov 15",
"content": [
{
"articleTitle":" 7 Things Every Designer Needs to Know about Accessibility",
"articleUrl":"https://medium.com/salesforce-ux/7-things-every-designer-needs-to-know-about-accessibility-64f105f0881b#.5pgg5014x?ref=boomkrak",
"articleAuthor": "Jesse Hausler",
"articleTag": "ux, web design, accessibility"
},
{
"articleTitle":"Get the most out of your research with storytelling",
"articleUrl":"https://blog.intercom.com/get-the-most-out-of-your-research-storytelling/?ref=boomkrak",
"articleAuthor": "Jillian Wells",
"articleTag": "design research, collaboration"
}
]
}
]
}
I want to show the article based on each tag. For example, if I want to show ux articles, then all articles with ux tag should be displayed.
Anyone know how to do it in Jekyll?

Considering that your datas are in _datas/articles.json, you can use this include file (_includes/listbyTag.html) :
{% assign tag = include.tag %}
{% assign days = site.data.articles.resources %}
{% assign list = ""| split: "/" %} {% comment %} creates an empty array {% endcomment %}
{% for day in days %}
{% for article in day.content %}
{% if article.articleTag contains tag %}
{% assign list = list | push: article %}
{% endif %}
{% endfor %}
{% endfor %}
{% if list.size != 0 %}
<h3>Found {{ list.size }} posts for tag : {{ tag }}</h3>
<ul>
{% for post in list %}
<li>{{ post.articleTitle }}</li>
{% endfor %}
</ul>
{% endif %}
Now you can include it anywhere with :
{% include listByTag.html tag="ux" %}
Or for a tag page :
---
tag: ux
title: my title
layout: default
---
{% include listByTag.html tag=page.tag %}

Related

Shopify Blocks CollectionList

I am trying to access and loop through the collection list inside the blocks:
The following code should loop through this collection list
<!-- If The Category Has So Many Subs -->
<div class="sub-cat-childs-container">
{% for block in section.blocks %}
{% case block.type %}
{% when 'Sub-Category' %}
{% if shop.locale == 'en' %}<style>.subCategory::after{float: right}</style>{% endif %}
<div class="sub--category--contnet" id="sub-category-{{ block.settings.sub_category_collection.id }}">
<div class="sub-sub---items-row">
Loop Throug The CollectionList {{ block.settings.sub-subcategory-collection_list }}
</div>
</div>
{% endcase %}
{% endfor %}
</div>
{% endif %}
The following is the schema I am trying to get the collection list from it:
{% schema %}
{
"name" : "Main Category",
"settings" :
[
],
"blocks" :
[
{
"name" : "Sub-Category",
"type" : "Sub-Category",
"settings" :
[
{
"type": "collection_list",
"id": "sub-subcategory-collection_list",
"label": "Sub Sub-Categories"
}
]
}
],
"presets" :
[
{
"name" : "Main Category"
}
]
}
{% endschema %}
Any one can help me to display all the collection in this collecion List
id:sub-subcategory-collection_list.
Thank you all...
You can create a new for loop to loop over the collections you have selected, for example:
{% for collection in block.settings.sub-subcategory-collection_list %}
{{ collection.title }}
{% endfor %}
The collection_list type gives you an array of Collection objects which you can loop over, as documented here
As a side note, you should aim to keep all your setting IDs as snake-case, to match Shopify's practice guides

loop through a for statement using an if/else with nunjucks and json

I'm trying to loop through a nested json file with nunjucks, give each object type a specific layout and sort all based on date.
So in my case I have two collections events and videos. Both collections will have an array of events and videos.
My file is named /content.json and structured as followed:
{
media: {
events: [
{
content_id: "1",
content_type: "event",
date: "01-11-2019",
etc: "etc"
},
{
content_id: "2",
content_type: "event",
date: "01-08-2019",
etc: "etc"
}
],
videos: [
{
content_id: "3",
content_type: "video",
date: "01-12-2019",
etc: "etc"
},
{
content_id: "4",
content_type: "video",
date: "01-09-2019",
etc: "etc"
}
]
}
}
I have tried to get the different object assigned with an if/else statement and then use a for loop to cycle through the array, but that has failed, see below:
{% for item in content.media %}
{% if item == events %}
{% for item in content.media.events %}
{% include "components/event.njk" %}
{% endfor %}
{% elif item == video %}
{% for item in content.media.videos %}
{% include "components/video.njk" %}
{% endfor %}
{% endif %}
{% endfor %}
I never got to try and sort all the content by date, but I have found:
{% for item in items|sort(attribute='date')%}
Can anyone guide me in right direction?
Thanks in advance.
AENM
This code outputs separated feeds by type of elements (event or video).
{% for event in content.media.events | sort(attribute = 'date') %}
{% include "components/event.njk" %}
{% endfor %}
{% for video in content.media.videos | sort(attribute = 'date') %}
{% include "components/video.njk" %}
{% endfor %}
If you need to output a mixed feed, you should join arrays to one and run trought it (fortunately each elements already have the type):
{% for item in [].concat(content.media.events, content.media.videos) | sort(attribute = 'date') %}
{% include "components/" + item.content_type + ".njk" %}
{% endfor %}
Aikon,
I got it now!!
It was another typo, you switched the media and events. (did you try to keep me sharp?! :-))
But that's why the concat didn't work!!
So this is the final working result:
{% for item in [].concat(media.content.events, media.content.videos) | sort(attribute = 'date') %}
{% include "components/" + item.type + ".njk" %}
{% endfor %}
Only the date is not in the correct order, but I think that has to with my grid setup.
Thanks for helping me out......

How can I access JSON identifiers from Twig?

These are my JSON data:
[
{
"name":"unit 1",
"lessons":{
"1":{
"name":"lesson 1",
"content":"......."
},
"2":{
"name" "lesson 2",
"content":"......."
}
}
]
I can access these data using the following Twig code:
{% for unit in units %}
{{ unit.name }}
{% for lesson in unit.lessons %}
{{ lesson.name }}
{% endfor %}
{% endfor %}
But I want to access the lesson number, to make a hyperlink to the content. How can I do that?
You can Iterating over Keys and values as example:
{% for key, lesson in unit.lessons %}
{{ key}}
{{ lesson.name }}
{% endfor %}
Hope this help

Show title only once inside django if statement

I have an car object in django view as follows:
'damages': [
{
"location": "Voorbumper",
"type": "Kras(10 cm, leger)",
"severity": "Light damage",
'comment': "This is some comment.",
"images": [
'http://pathtophoto.jpg',
'http://pathtophoto.jpg'
]
},
{
"location": "Vleugel rechts voor",
"type": "Deuk (Licht)",
"severity": "",
'comment': "",
"images": [
'http://pathtophoto.jpg',
'http://pathtophoto.jpg',
'http://pathtophoto.jpg'
]
},
{
"location": "Deur links voor",
"type": "Kras (5 cm, leger)",
"severity": "",
'comment': "",
"images": [
'http://pathtophoto.jpg'
]
},
{
"location": "Waterlijst",
"type": "Beschadigd",
"severity": "",
'comment': "",
"images": []
},
{
"location": "Antenne",
"type": "Ontbreekt",
"severity": "",
'comment': "",
"images": [
'http://pathtophoto.jpg'
]
},
{
"location": "Antenne",
"type": "Ontbreekt",
"severity": "",
'comment': "",
"images": []
}
]
I want to loop through that object and show the images of the damages. But I want first to show the damages with images, and the the damages without images with appropriate title.
In a django template I try to d it as follows:
{% for damage in car.damages %}
{% if damage.images|length > 0 %}
<div class="width-100 pad text-left primary-bg">{% trans "Shades met foto's" %}</div>
<div class="width-100 mar-top clear-float">
<div class="width-30 bord-my-way pad-half damage-info">
<div class="mar-btm-half"><b>{{ damage.location }}</b></div>
<div class="mar-btm-half">{{ damage.type }}</div>
<div class="mar-btm-half">{{ damage.severity }}</div>
<div class="mar-btm-half">{{ damage.comment }}</div>
</div>
<div class="width-70 pad-lft damage-photos">
{% for image in damage.images|slice:"3" %}
<div class="width-33 pad-rgh">
<img src="{{ image }}" class="width-100"/>
</div>
{% endfor %}
</div>
<div class="clear-float"></div>
{% if forloop.counter == 7 or forloop.counter == 14 or forloop.counter == 21 %}
<p style="page-break-before: always"></p> {% endif %}
</div>
{% endif %}
{% endfor %}
{% for damage in car.damages %}
{% if damage.images|length == 0 %}
<div class="width-100 pad text-left primary-bg mar-top">{% trans "Shades zonder foto's" %}</div>
<div class="green-bg">{{ damage.location }}</div>
{% endif %}
{% endfor %}
Thus, I first loop through damages where damage.images|length > 0 and then in the second for I check if there is no images with damage.images|length == 0. But the title is shown for every for loopiteration.
I could place the title's for the for loop. Something like:
<div> Damages with photos </div>
{% for damage in car.damages %}
{% if damage.images|length > 0 %}
// Show it
{% endif %}
{% endfor %
And
<div> Damages without photos </div>
{% for damage in car.damages %}
{% if damage.images|length == 0 %}
// Show it
{% endif %}
{% endfor %
But sometimes I have only damages with images or only damages without images and then I see the title although I do not have any damages to show.
Is there any way to do something only once inside the if statement, something like:
{% for damage in car.damages %}
{% if damage.images|length > 0 %}
<div>Damages with the photos</div> // Show it only once when it comes here
// Show the damages with photos
{% endif %}
{% endfor %}
{% for damage in car.damages %}
{% if damage.images|length == 0 %}
<div>Damages without the photos</div> // Show it only once when it comes here
// Show the damages without photos
{% endif %}
{% endfor %}
Any idea how to solve it?
I'm not overly familiar with Django and Python anymore, but I guess you could do a preliminary check to see if there are damages with or without images in there.
damages_with_images = [d for d in damages if d.images.length > 0]
damages_without_images = [d for d in damages if d.images.length == 0]
And then just loop over these two separate arrays, and only print the heading if they are not empty...
{% if damages_with_images|length > 0 %}
put heading1
{% endif %}
# ... loop ...
{% if damages_without_images|length > 0 %}
put heading2
{% endif %}
# ... loop ...
Of course this has worse performance because of multiple loops.
What I would do in your position is
Either pass two separate QuerySets in the template, the first would include damages with images and the other damages without images.
Leave the QuerySet as is and create two custom template filters that would do the same job as the step #1 above.
Case 1:
# views.py
def my_view(request):
damages_w_img = Damage.objects.filter(images__isnull=False)
damages_wo_img = Damage.objects.filter(images__isnull=True)
return render(request, 'template.html', locals())
<!-- template.html -->
{% if damages_w_img.exists %}
<h1>This list of damages contains images</h1>
{% for damage in damages_w_img %}
do stuff here, each damage has an image
{% endfor %}
{% endif %}
{% if damages_wo_img.exists %}
<h1>This list of damages does not contain images</h1>
{% for damage in damages_wo_img %}
do stuff here, each damage does not has an image
{% endfor %}
{% endif %}
Case 2:
# custom_template_filter.py
from django import template
register = template.Library()
#register.filter
def with_images(damages):
return damages.objects.filter(images__isnull=False)
#register.filter
def without_images(damages):
return damages.objects.filter(images__isnull=True)
<!-- template.html -->
{% with damage_w_img=car.damages|with_images damage_wo_img=car.damages|without_images %}
{% if damages_w_img.exists %}
<h1>This list of damages contains images</h1>
{% for damage in damages_w_img %}
do stuff here, each damage has an image
{% endfor %}
{% endif %}
{% if damages_wo_img.exists %}
<h1>This list of damages does not contain images</h1>
{% for damage in damages_wo_img %}
do stuff here, each damage does not has an image
{% endfor %}
{% endif %}
{% endwith %}

Shopify Liquid capture settings not outputting for some reason

I'm trying to get and display some theme settings which gets the site name and applies to end which i have setup in the schema but cant get it to display the settings.
In the promo_header.liquid snippet file i have:
{% capture promo_header_text_1 %} locale_promo_1_text_{{ shop.name }} {% endcapture %}
{% capture promo_header_url_1 %} locale_promo_1_url_{{ shop.name }} {% endcapture %}
{% capture promo_header_text_2 %} locale_promo_2_text_{{ shop.name }} {% endcapture %}
{% capture promo_header_url_2 %} locale_promo_2_url_{{ shop.name }} {% endcapture %}
<p>
{% if settings[promo_header_text_1] %}
{{ settings[promo_header_text_1] }}
{% endif %}
{% if settings[promo_header_text_2] %}
<span>/</span>{{ settings[promo_header_text_2] }}
{% endif %}
</p>
I have also tried to output using just for example
{{ settings.promo_header_text_1 }}
But not displaying anything either... when i debug and display for example
{{ promo_header_text_1 }}
It does return
locale_promo_1_text_website-test2
Which is correct and in the schema settings file (example based on that one above it is matching and is set in theme customisation)
{
"type": "text",
"id": "locale_promo_1_text_website-test2",
"label": "Promo 1 Text",
"default": "FREE US SHIPPING OVER $35"
}
What am I doing wrong?
For anyone else that might come across the same issue here is the solution I got working:
{% assign promo_header_text_1 = 'locale_promo_1_text_' | append:shop.name %}
and to output
{{ settings[promo_header_text_1] }}