In Mustache, is there a way to check of the list has items, but not repeat it? - mustache.php

I would like to be able to check if a list is empty, and if it's not print a block, but I don't want to repeat that block for each item. I just want to be able to echo it once.
Give this following structure:
array(
"teasers" => array(
array("title"=>"Teaser Title 1"),
array("title"=>"Teaser Title 2")
)
);
{{# teasers }}
<div class="items-wrap">
<div class="items">
{{# . }}
<div class="item">
{{ title }}
</div>
{{/ . }}
</div>
</div>
{{/ teasers }}
I would like the items-wrap div to only print once, and repeat the item div for each item in the array. As is right now, the items-wrap is repeating once for each item in the teasers array. So... is there a way to check if the main array is not empty, but not repeat it?
The goal is to only print the items-wrap once, if needed.

Yes, there's a way. Mustache has the method length. If equal ZERO, is false and the block will not be rendered. Your example:
{{# teasers.length }}
<div class="items-wrap">
<div class="items">
{{# teasers }}
<div class="item">
{{ title }}
</div>
{{/ teasers }}
</div>
</div>
{{/ teasers.length }}
The tag {{teasers.length}} will check the number of items inside {{teasers}} and will render the block only if not empty.
More information here.
This answer is too late, but I hope it helps someone.

In terms of PHP:
{{#myArray.0}}...{{/myArray.0}}
https://stackoverflow.com/a/23786928/5546916

user "_has_items" , example: myarray_has_items willcheck the contion whether arry is empty or not then the tag wont render
or you can use {{#items.length}} to check length before render
{{#items.length}}
<ul>
{{items}}
<li>{{name}}</li>
{{/items}}`enter code here`
</ul>
{{/items.length}}

Related

How does Laravel turn this code into a link?

Consider this block of code from a Laravel blade file:
<div class="result-content">
<h6>{{ $item->name }}</h6>
<div>{!! Str::limit($item->desccription, 120) !!}</div>
#if($item->type == 'lot')
<div>{{ $item->info ? "Current Bid: $".number_format($item->info, 2) : 'No bids yet' }}</div>
<div>{{ \Carbon\Carbon::parse($item->start)->setTimezone($_COOKIE['timezone'])->format('n/j/y g:ia T') }} - {{ \Carbon\Carbon::parse($item->end)->setTimezone($_COOKIE['timezone'])->format('n/j/y g:ia T') }}</div>
#else
<div>{{ $item->info }} Lot{{ $item->info > 1 ? "s" : '' }}</div>
<div>{{ \Carbon\Carbon::parse($item->start)->setTimezone($_COOKIE['timezone'])->format('n/j/y T') }} - {{ \Carbon\Carbon::parse($item->end)->setTimezone($_COOKIE['timezone'])->format('n/j/y T') }}</div>
#endif
<a href="{{ $item->search_url }}" title="">
View: {{ $item->search_title }}
</a>
</div>
Somehow or other, this renders in a browser as a block of text that is all included in a link tag, and "$item->search_url" becomes the link url. But the link is wrong - it just points back to the page this text is appearing on. I need to figure out where "search-url" is assigned its value, so I can fix it. But I am entirely new to Laravel, and I can't figure out where or how "search-url" is getting assigned a value. I've searched the entire system with Visual Code, and that name doesn't appear anywhere else. It's not a variable, it's not a property name, it's not a database field name.
Where is that variable getting assigned?

Laravel Components: default content in {{ slots }}

In old-style Laravel blade templated we used to use #section('section-name') in the following way:
{{-- h1para.blade.php --}}
<h1>
#section('heading')
Heading from Template
#endsection
</h1>
<p>
#yield('details')
</p>
And then extend that template with:
{{-- content.blade.php --}}
#extends('h1para')
#section('details')
Content from content page
#endsection
In the above, my rendered HTML output would look like the following, because the "missing" 'heading' section in the extending file means that we default back to the content in the template:
<h1>Heading from Template</h1>
<p>Content from content page</p>
But in the new components way of doing things, I do:
{{-- .../components/h1para.blade.php --}}
<h1>{{ $heading }}</h1>
<p>{{ $slot }}</p>
In case you haven't gathered, the question is: how do I set a default value for a slot's contents, such that if it isn't supplied in the extending component/template, it falls back to that default?
(I've done my searches, but haven't been able to find the same question asked before)
EDIT:
I should add that I've seen the solution (in the Laravel documentation):
<h1>{{ $heading ?? 'Default Heading Here' }}</h1>
But this seems only to be appropriate if the default value is a short easy to manage string. If the default is a long stream of HTML, then it wouldn't work for my needs.
EDIT 2:
Just to reiterate: the whole point of the question is that the default content could be a long stream of HTML. Solving the problem by passing in a string (be that formatted as HTML or not) wouldn't work for my real-world needs.
I think the solution is this:
{{-- .../component/template.blade.php --}}
<div>
#if (isset($heading))
{{ $heading }}
#else
<h1>Default Heading<span class="subhead">default subheadin and lots of other html content</span></h1>
#endif
<p>{{ $slot }}</p>
</div>
It's not super elegant, but I think it's the only solution. Anyone else have a better answer, I'd love to hear it.
If you pass data like:
<x-h1para header="<span>Header content</span>">
<div>Default slot content here</div>
</x-h1para>
You can display in your component like:
<div>
<h1>{!! $heading ?? 'Default Heading Here' !!}</h1>
{{ $slot }}
</div>

Hugo: How can I display an image in my post list

I am trying to display an image in my post list.
In order to achieve that I added some tags in my post.md:
---
title: "Hello"
header_image: /images/blog/2019/water.jpg
images: /images/blog/2019/water.jpg
resources:
src: /images/blog/2019/water.jpg
title: "The image I want"
---
Then I edited list.html and tried different things:
{{ define "main" }}
<div class="archive animated fadeInDown">
<ul class="list-with-title">
<div class="listing-title">{{.Title}}</div>
{{ range .Pages }}
<ul class="listing">
<div class="listing-item">
<div class="listing-post">{{ .Title }}
{{ with .Resources.ByType "image" }}
<div class="Image">
{{ range . }}
<img src="{{ .RelPermalink }}">
{{ end }}
</div>
{{ end }}
{{ $.Param "header_image" }}
-- {{ range .Page.Resources }}
THERE IS ONE ITEM => NOT WORKING
{{ end }} <<
<div class="post-time"><span class="date">{{.Date.Format "Jan 2" }}</span></div>
</div>
</div>
</ul>
{{ end }}
</div>
{{ end }}
But when I try to display Resources, I always get [] (nothing)
Any idea what I am doing wrong?
I don't think your {{ $.Param "header_image" }} is working, either.
The way to access your custom, non-standard variables on pages, as well as sites, is through the .Params object, e.g. .Params.header_image. Note the small letter at the beginning, as opposed to capital letters for built-in params.
Page-level params on the Hugo Docs
Custom page params
To access
---
header_image: /images/blog/2019/water.jpg
---
you can use this in your page template.
{{ .Params.header_image }}
Resources
Page resources on Hugo Docs
It seems that resources is actually an array of objects, and with yaml, you should actually have something like this (note the dash):
resources:
- src: /images/blog/2019/water.jpg
title: "The image I want"
Also mind that this feature seems to only be available only for page bundles
Debugging
You can use {{ printf "%#v" .Resources }} for debugging.

Blade Component to create Menus or Lists

I was looking for a while a way to create a component but to create as many slots as needed dinamically.
For example, you want to repeat a menu list style in your project multiple times, the best option is to have a component, but what if i need custom html options each element, that makes it tricky.
The best option so far i get is the following, hope someone finds it helpfull
In your view file:
#component('components.radioList',['values'=>[1,2,3,4],'name'=>'myname'])
#slot('html_0')
mi html item 0
#endslot
#slot('html_1')
mi html item 1
#endslot
#slot('html_2')
mi html item 2
#endslot
#slot('html_3')
mi html item 3
#endslot
#endcomponent
In your component blade:
<ul class="list-group">
#foreach($values as $value)
#isset(${"html_{$loop->index}"})
<li class="list-group-item custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="customCheck_{{$loop->index}}" name="{{$name}}" value="{{$value}}">
<label class="custom-control-label" for="customCheck_{{$loop->index}}">
{{ ${"html_{$loop->index}"} }}
</label>
</li>
#endisset
#endforeach
</ul>
The only thing is that the values, and the amount of slots needs to match.
If you dont need extra values for each slot, you can create as a count:
#component('components.radioList',['count'=>4,'name'=>'myname'])
And change the Foreach to a For
Cheers!

Hugo definition of non-site level variables/parameters query

I am using Hugo Universal Theme. I am new to static site generators. This question is for someone who is familiar with hugo templates.
In layouts/partials/features.html we can see where $element.name and $element.name.description are rendered:
{{ if isset .Site.Params "features" }}
{{ if .Site.Params.features.enable }}
{{ if gt (len .Site.Data.features) 0 }}
<section class="bar background-white">
<div class="container">
{{ range $index, $element := sort .Site.Data.features "weight" }}
{{ if eq (mod $index 3) 0 }}
<div class="col-md-12">
<div class="row">
{{ end }}
<div class="col-md-4">
<div class="box-simple">
<div class="icon">
<i class="{{ .icon }}"></i>
</div>
<h3>{{ $element.name }}</h3>
<p>{{ $element.description | markdownify }}</p>
</div>
</div>
{{ if or (eq (mod $index 3) 2) (eq $index (sub (len $.Site.Data.features) 1 )) }}
</div>
</div>
{{ end }}
{{ end }}
</div>
</section>
{{ end }}
{{ end }}
{{ end }}
The data to be rendered in this case are defined in data/features/consulting.yaml as follows:
weight: 4
name: "Consulting"
icon: "fa fa-lightbulb-o"
description: "Fifth abundantly made Give sixth hath..."
What should I do to add new variable to the yaml file that can later then be rendered through the html file when hugo is compiling the site. I tried to simply add another parameter param1 and then insert a corresponding line in the html file as <p>{{ $element.param1 | markdownify }}</p> just below description paragraph but got error
ERROR 2018/08/23 10:42:42 Error while rendering "home" in "":
template: index.html:22:11: executing "index.html" at <partial
"features.ht...>: error calling partial: template:
partials/features.html:18:56: executing "partials/features.html" at
: wrong number of args for markdownify: want 1 got 0
Clearly it seems I have not been able to define the variable properly, but where should I do that? I can add another site variable to config.toml, but I want to learn how to make page specific variables that can be defined in yaml/frontmatter type entries. I tried reading about hugo variables but got bogged down in what is a variable and what is a shortcode. Many thanks for your help with this example.
Well, I found a working answer, but I still do not fully understand how it fits with Hugo variable system, so a better answer and or comments are highly welcome.
It appears quite simple. I had to define url variable in the yaml file:
name: "History"
position: "Hx"
url: "/blog/2018/08/23/01-history/"
and then use in the html file like this:
{{ if .url }}
<a href="{{ .url }}">
<h5>{{ .name }}</h5>
</a>
{{ else }}
<h5>{{ .name }}</h5>
{{ end }}
What it does is puts the .name in link tag, if .url is defined in .yaml. This works also if an absolute URL is given. So it appears that a page variable is referred to as .myVariable. the template authors used $element.name in another place as above, which confused me.
I also can refer to the parameter defined in the frontmatter as .Params.name
I found pointers at https://github.com/devcows/hugo-universal-theme/pull/166 and tested in adjusting the template; it works well.

Resources