I would like to implement a News Headline banner.
The HTML code for that headline banner is this:
<!-- hot news start -->
<div class="col-sm-16 hot-news hidden-xs">
<div class="row">
<div class="col-sm-15"> <span class="ion-ios7-timer icon-news pull-left"></span>
<ul id="js-news" class="js-hidden">
<li class="news-item"><a href="">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor</a></li>
<li class="news-item"><a href="">Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium</a></li>
<li class="news-item"><a href="">Donec quam felis, ultricies nec, pellentesque eu</a></li>
<li class="news-item"><a href="">Nulla consequat massa quis enim. Donec pede justo, fringilla</a></li>
<li class="news-item"><a href=""> Donec pede justo, fringilla vel, aliquet nec, vulputate eget ultricies nec, pellentesque</a></li>
<li class="news-item"><a href="">In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo</a></li>
<li class="news-item"><a href="">Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis </a></li>
</ul>
</div>
<div class="col-sm-1 shuffle text-right"><a href="#"><span class="ion-shuffle"></span></a></div>
</div>
</div>
<!-- hot news end -->
I would like to make this so it can be used in a modular page. The idea is that the user could just type something similar to this:
news:
text: Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
url: foo.com/lorem
news:
text: Sed ut perspiciatis unde omnis iste natus error sit voluptatem
url: foo.com/sedut
...
And the whole block would be rendered. I would like to know how to implement that in Grav/Twig. If someone answers please bear in mind that I am relatively new to Grav, so a verbose answer is more appreciated than a concise one.
I will begin with the simplest solution that would achieve your goal. At first, I will treat this as a regular page, not a modular page.
In your user file, let's define a new template within your current template. Antimatter is the default one, so I'll work with this one. Create news.html.twig in user - templates - antimatter folder and paste in the following code block.
{# user/templates/antimatter/news.html.twig #}
<div class="col-sm-16 hot-news hidden-xs">
<div class="row">
<div class="col-sm-15"> <span class="ion-ios7-timer icon-news pull-left"></span>
<ul id="js-news" class="js-hidden">
{% for news in page.header.news %}
<li class="news-item"><a href="{{news.url}}">{{news.text}}</a></li>
{% endfor %}
</ul>
</div>
<div class="col-sm-1 shuffle text-right"><a href="#"><span class="ion-shuffle"></span></a></div>
</div>
This is a twig way how to loop through the frontmatter content which we'll create now. All the pages in Grav are stored in user - pages folder. The name of the folder specifies among others the relative address of the page, the number is just for ordering purposes and irrelevant for now, the markdown file inside specifies which template to use.
Let's create in pages a folder called 02.news and inside a file called news.md. Therefore, it'll use news template we created earlier. Paste this into the news.md
<!-- user/pages/02.news/news.md -->
---
news:
-
text: Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
url: foo.com/lorem
-
text: Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
url: foo.com/lorem
-
text: Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
url: foo.com/lorem
---
Doing this we create a news array and each entry has text and url. Now you have access to it through page.header.news and you can retrieve it's attributes.
I'm not all too sure how would you imagine turning this into a modular design. One way that comes to mind is to have a parent page and within have modular pages for various topics such as business news or politics. Let's try that.
Start with a parent template, let's call it a newscontainer.html.twig. In it we need to specify that grav should retrieve all it's modular children and iterate over. Grav calls these children a collection of pages. We'll just want to spit out their content.
{# user/templates/antimatter/newscontainer.html.twig #}
{% for module in page.collection() %}
{{module.content}}
{% endfor %}
Now in the 02.news folder, change the markdown file name to newscontainer so it uses our new template. Now it serves as a parent container for all the news. Inside, specify that it should load into it's page.collection all it's modular children. The limit means that maximum 20 modular pages will be loaded.
<!-- user/pages/02.news/newscontainer.md -->
---
title: News
content:
items: '@self.modular'
limit: 20
---
In the templates folder, create a new one called modular and move the news.html.twig template we made earlier into it. Modular pages look for templates in this folder.
Almost there. Lastly, in 02.news folder, we can now create modular pages. You can do that by creating new folders that start with _ instead of numbers, so for example create _politics and _business. You can copy now the news.md we made earlier into each and change the content as you wish. It should display correctly if you go to whateverpage.com/news
In the end, the pages structure looks like this
pages
01.Home
default.md
02.News
newscontainer.md
_business
news.md
_politics
news.md