I got some help generating JSON from folder structure via Grunt. That worked great.
Now, I want to take that JSON and create a menu based on the output.
Here is a sample of what I'm talking about.
{
"files": [
{
"name": "firstpage.twig",
"path": "folder1/subfolder1"
},
{
"name": "secondpage.twig",
"path": "folder1/subfolder1"
},
{
"name": "thirdpage.twig",
"path": "folder1/subfolder1"
},
{
"name": "fourthpage.twig",
"path": "folder1/subfolder1"
},
{
"name": "anotherpage.twig",
"path": "folder1/subfolder2"
},
{
"name": "yetanother.twig",
"path": "folder1/subfolder2"
},
{
"name": "heresanother.twig",
"path": "folder2/subfolder3"
},
{
"name": "anotherone.twig",
"path": "folder2/subfolder3"
}
]
}
I'd like to build a nav so that it would be like
<ul>
<li>
folder1
<ul>
<li>
subfolder1
<ul>
<li>firstpage</li>
<li>secondpage</li>
<li>thirdpage</li>
<li>fourthpage</li>
</ul>
subfolder2
<ul>
<li>anotherpage</li>
<li>yetanother</li>
</ul>
</li>
</ul>
</li>
<li>
folder2
<ul>
<li>
subfolder3
<ul>
<li>heresanother</li>
<li>anotherone</li>
</ul>
</li>
</ul>
</li>
</ul>
The sections of folder1, subfolder1, etc would be dynamically populated based off of going through the path entries within the JSON and parsing the unique ones out.
I am using a Grunt custom task to generate the JSON. I also am using Twig that gets rendered via a Twig Rendering Grunt package. There is no other framework to play with here, just pure Twig. It's all done through NPM.
I tried this so far but am obviously failing
{% for folder in files %}
{% set folders = folder.path|split('/') %}
{% for i in folders if i (doesn't already exist) %}
// Dynamic menu goes here
{% endfor %}
{% endfor %}
Just stuck here banging my head off the desk. :)
Thanks in advance for any help!
In the Gruntfile, the custom task that works is like this:
grunt.registerTask('twigList', 'Creates list of twig files', function() {
var obj = {};
obj.files = find('sections')
.filter(function(filePath) {
return filePath.match(/\.twig$/);
})
.map(function(filePath) {
let itemPath = path.dirname(filePath).replace('sections/','');
let pathSeparatorPos = itemPath.indexOf('/');
let rootPath = itemPath.substring(0, pathSeparatorPos);
return {
name: path.basename(filePath),
path: itemPath,
rootPath: rootPath,
}
});
grunt.file.write('data/page-list.json', JSON.stringify(obj, null, 2));
});
and then the quick and dirty twig is this
{% set _lastRootPath = false %}
{% for folder in files if folder.rootPath is not empty %}
{% if folder.rootPath != _lastRootPath %}
{% set _lastRootPath = folder.rootPath %}
{{ folder.rootPath }}
{% endif %}
{% endfor %}
{% set _lastRootPath = false %}
<ul>
{% for folder in files if folder.rootPath is not empty %}
{% if folder.rootPath != _lastRootPath %}
{% if _lastRootPath != false %}</ul></li>{% endif %}
{% set _lastRootPath = folder.rootPath %}
<li>{{ folder.rootPath }}<ul>
{% endif %}
{% if folder.rootPath == _lastRootPath %}
<li>{{ folder.name }}</li>
{% endif %}
{% endfor %}
It's not polished but it works
Related
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
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......
I am being passed an array that unfortunately I cannot restructure:
"options": [
{"name":"namea","text":"valuea"},
{"name":"nameb","text":"valueb"},
{"name":"namec","text":"valuec"},
{"name":"named","text":"valued"}
]
I need to be able to find the object with the name equal to namea, nameb, namec, etc. and then produce the appropriate text. I tried the following and few other variations of that but could not get it to work:
{% for item in event.options %}
{% if item.name == "nameb" %}
{{ item.text|capitalize }}
{% endif %}
{% endfor %}
Thanks in advance for any help.
Edit: I basically only have access to a text box to input HTML and Twig. I do not have access to framework, custom extensions, etc.
Edit: JSON with exact formatting:
{
"source": "TEST.COM",
"trigger": "test",
"options": [{
"name":"test_date",
"value":"31-05-2017"
},
{
"name":"test_number",
"value":"9081003"
},
{
"name":"test_test",
"value":"9asd003"
},
{
"name":"Name",
"value":"Todd"
},
{
"name":"test_other",
"value":"kslkjsfd"
},
{
"name":"test_help",
"value":"908sdf3"
}]
}
This is going to be very hacky either way (I feel the javascript way as mentioned in the comments would still be less hacky).
However as its multilined we could write a basic parser like thing (this is by no means bullet proof and fails if the content has a ", or the structure changes or whatever changes to be honest):
{# create an array of lines #}
{% set event = event|split('\n') %}
{# an array to hold our options #}
{% set options = [] %}
{# using a bool to track if we are inside the options part #}
{% set inOptions = false %}
{# this holds the name of the last name value we have passed #}
{% set currentKey = '' %}
{# go through each line #}
{% for line in event %}
{# if we are inside the options tag do our magic #}
{% if inOptions %}
{# check if the line starts with "name": and track the current key name #}
{# or check if it starts with "value": and set the current key to that value #}
{% if line matches '/"name":/' %}
{# split line on the double quotes and get the last bit #}
{% set currentKey = line|split('"') %}
{# cant get the array index piped in one go idk.. #}
{% set currentKey = currentKey[3] %}
{% elseif line matches '/"value":/i' %}
{% set currentValue = line|split('"') %}
{% set options = options|merge({(currentKey): currentValue[3]}) %}
{% elseif line matches '/\s*}]/' %}
{% set inOptions = false %}
{% endif %}
{% endif %}
{# check for the options sectioning start #}
{% if line matches '/^"options/' %}
{% set inOptions = true %}
{% endif %}
{% endfor %}
{{ dump(options) }}
This returns in my dump (which you didn't have so you cant see):
array:6 [▼
"test_date" => "31-05-2017"
"test_number" => "9081003"
"test_test" => "9asd003"
"Name" => "Todd"
"test_other" => "kslkjsfd"
"test_help" => "908sdf3"
]
As an actual array where you can then call options.test_date but all this is super hacky, it still can be improved but twig is not made for it and the syntax gets so clunky its hard to maintain.
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 %}
Given this JSON:
case studies: [
[ "Nubaru",
["Nubaru Yearly Report", "Web design", "2013", "/case-studies/Nubaru.html", "/images/case-studies/Nubaru.png"]
],
[ "Ekande",
["Ekande application", "Web application design", "2013", "/case-studies/Ekande.html", "/images/case-studies/Ekande.png"]
]
]
And this Liquid (using Jekyll):
<ul>
{% for items in page.case-studies %}
{% for item in items %}
<li>
{{ item }}
<!-- How to get sub items? -->
</li>
{% endfor %}
{% endfor %}
</ul>
How would I access the data in the inner array?
Is there a way to name the data so I might access it like this: {{ case-study.date }}?
For the first question, have you tried using a third loop like {% for subItem in {{ item[2] }} %}, or accessing directly, like for the data {{ item[2][3] }} ?
For the second one, you can use {% assign %} like this: {% assign caseDate = 'your-value' %}, cf. http://wiki.shopify.com/Liquid#Variable_Assignment