Conditional Blade component slots - php

I have a Blade component called persons, that has different slots I'd like to fill.
<div class="person">
<img src="{{ $image_url }}" alt="{{ $image_alt }}">
{{ $name }}
{{ $information }}
<a class="button button-primary" href="{{ $link }}" target="_blank">Homepage</a>
</div>
And I have various template files, where I'm doing a foreach and I'd like to use the persons component to show the info.
#if ($persons)
#foreach ($persons as $person)
#component('components.person')
#slot('image_url')
{{ $person['person_image'] }}
#endslot
#slot('name')
{{ $person['person_name'] }}
#endslot
#slot('information')
{!! $person['person_information'] !!}
#endslot
#slot('link')
{{ $person['person_link'] }}
#endslot
#endcomponent
#endforeach
#endif
Sometimes some fields might be empty. For example, sometimes somebody doesn't have an image or a homepage and in that case I'd wouldn't want to show that empty field on the homepage.
Logic says that I should add issset() or empty() into my component file, like this:
<div class="person">
#empty ($image_url)
<img src="{{ $image_url }}" alt="{{ $image_alt }}">
#endempty
#isset ($name)
{{ $name }}
#endisset
#isset ($information)
{{ $information }}
#endisset
#isset ($link)
<a class="button button-primary" href="{{ $link }}" target="_blank">Homepage</a>
#endisset
</div>
But this doesn't seem to work at all. It either removes everything or nothing at all ( depending on if using #isset() or #empty() ).
So my question is: Is it possible to fill component slots conditionally in a foreach loop?

This is from a while ago, but you can use the null coalesce operator to define a default
<div class="person">
<img src="{{ $image_url }}" alt="{{ $image_alt }}">
{{ $name ?? '' }}
{{ $information ?? '' }}
<a class="button button-primary" href="{{ $link }}" target="_blank">Homepage</a>
</div>

Use #if and the null coerce operator and set the default value:
<div class="person">
#if ($image_url ?? null)
<img src="{{ $image_url }}" alt="{{ $image_alt ?? '' }}">
#endif
<span>{{ $name ?? 'No name' }}</span>
{{ $information ?? null }}
#if ($link ?? null)
<a class="button button-primary" href="{{ $link }}" target="_blank">Homepage</a>
#endif
</div>

it is better to check them in the upper level as you said, but notice that you should pass something into slots if they have name slot, so you should call:
#slot('myslot')
#if($myobject->value)
<h5>
Show
</h5>
#endif
#endslot

This works for me.
#isset($qualitycheck)
<a class="dropdown-item p-2" href="{{ $qualitycheck }}">Quantity Check</a>
#endisset

Related

Blade and the Negative case

I'm sorry I do not know how to word this question. I'm new to Laravel and I want to either show a photo(s) or if there are no photos I want to show a placeholder. This works but there must be a better way to do it than this.
#foreach ($items as $item)
<?php $totalpics=0; ?>
<div class="col-md-4">
<div class="card mb-4 box-shadow">
#if(! empty($item->photos) )
#foreach ( $item->photos as $photo )
#if ($photo->photo)
<img src="/storage/images/small/{{ $photo->photo }}" class="card-img-top" alt="{{ $item->name }}">
<?php $totalpics++; ?>
#endif
#endforeach
#if(1 > $totalpics)
<img class="card-img-top" data-src="holder.js/100px225?theme=thumb&bg=55595c&fg=eceeef&text=Thumbnail" alt="{{ $item->name }}">
#endif
You want to achieve a for loop and an optional statement for when there is nothing to show in the for loop.
Laravel uses the forelse loop for this (see all blade loops in the documentation).
A basic forelse could be:
#forelse($items as $item)
{{$item}}
#empty
There are no items to display
#endforelse
Above code is pseudo code and would not actually run
Which would render as either all the items or as the text There are no items to display.
In your case you could use:
#forelse($items as $item)
<div class="col-md-4">
<div class="card mb-4 box-shadow">
#forelse ( $item->photos as $photo )
#if ($photo->photo)
<a href="/storage/images/large/{{ $photo->photo }}">
<img src="/storage/images/small/{{ $photo->photo }}" class="card-img-top" alt="{{ $item->name }}">
</a>
#endif
#empty
<a href="/items/{{ $item->id }}">
<img class="card-img-top" data-src="holder.js/100px225?theme=thumb&bg=55595c&fg=eceeef&text=Thumbnail" alt="{{ $item->name }}">
</a>
#endforelse
</div>
</div>
#endforeach
Side note, this will not render any photos if there is a photo model attached to your item but the photo model does not have the photo property set, i.e. the for loop will be used but the if statement will fail.
You can do
#foreach ($items as $item)
<div class="col-md-4">
<div class="card mb-4 box-shadow">
#unless($item->photos)
<img class="card-img-top" data-src="holder.js/100px225?theme=thumb&bg=55595c&fg=eceeef&text=Thumbnail" alt="{{ $item->name }}">
#else
#foreach ( $item->photos as $photo )
#if ($photo->photo)
<img src="/storage/images/small/{{ $photo->photo }}" class="card-img-top" alt="{{ $item->name }}">
#endif
#endforeach
#endunless
There is another way to do that in laravel 5.3+ by using
#forelse($item->photos as $photo)
<img src="/storage/images/small/{{ $photo->photo }}" class="card-img-top" alt="{{ $item->name }}">
#empty
<img class="card-img-top" data-src="holder.js/100px225?theme=thumb&bg=55595c&fg=eceeef&text=Thumbnail" alt="{{ $item->name }}">
#endforelse

How to create dynamic layout in Laravel with Blade?

So I'm building my first blog, and I'd like to dynamically show to posts on my landing page. I want the layout to become like this (might be a little weird):
post-image - post-preview
post-preview - post-image
post-image - post-preview
This is what I have right now to show to blog posts:
#foreach($posts as $post)
<div class="col-sm-4">
<a href="/post/{{ $post->slug }}">
<img src="{{ Voyager::image( $post->image ) }}" class="img-responsive" style="width:100%">
<span>{{ $post->title }}</span>
</a>
</div>
#endforeach
web.php (route):
$posts = App\Post::take(3)->orderBy('created_at')->get();
return view('welcome', compact('posts'));
Now as I'd like to make the layout dynamically. I think I can do this by checking if the ID even or odd. However I have no idea on how to do this even when I've searched 50% of the web already :) .
If there is a better way on doing this just let me know! Greatly appreciated guys!
Yes you can do it by checking if current post or loop iteration is odd or even. (https://laravel.com/docs/5.5/blade#the-loop-variable) For Odd loop iteration, you can write image code first and in even loop iteration you can write preview code first to achieve your desired layout. You can check the following code:
#foreach($posts as $post)
<div class="row">
#if( $loop->iteration % 2 == 0 )
<div class="col-md-4">
<a href="/post/{{ $post->slug }}">
<img src="{{ Voyager::image( $post->image ) }}" class="img-responsive" style="width:100%">
</a>
</div>
<div class="col-md-8">
<span>{{ $post->title }}</span>
</div>
#else
<div class="col-md-8">
<span>{{ $post->title }}</span>
</div>
<div class="col-md-4">
<a href="/post/{{ $post->slug }}">
<img src="{{ Voyager::image( $post->image ) }}" class="img-responsive" style="width:100%">
</a>
</div>
#endif
</div>
#endforeach
Ok I guess I got your question. so there is no direct solution but you can measure inside your for loop by adding extra variable such as:
<?php $inc = 0;?>
#foreach($posts as $post)
<div class="col-sm-4">
<a href="/post/{{ $post->slug }}">
#if($inc%2 == 0)
<img src="{{ Voyager::image( $post->image ) }}" class="img-responsive" style="width:100%">
<span>{{ $post->title }}</span>
#else
<span>{{ $post->title }}</span>
<img src="{{ Voyager::image( $post->image ) }}" class="img-responsive" style="width:100%">
#endif
<?php $inc++;?>
</a>
</div>
#endforeach
Or you can use for loop instead of foreach of loop and inside for loop you can check variable i.e. i is odd or even.

Different default template loading even though i have set routing correctly

In my views folder i have layouts/main.blade.php and under store/index.blade.php i am using the layout file like so:
#extends('layouts.main') // importing here.
#section('promo')
<section id="promo">
<div id="promo-details">
<h1>Today's Deals</h1>
<p>Checkout this section of<br/>
products at a discounted price.</p>
Shop Now
</div><!-- end promo-details -->
{{ HTML::image('img/promo.png' , 'Promotional Ad') }}
</section><!-- promo -->
#stop
#section('content')
<h2>New Products</h2>
<hr>
<div id="products">
#foreach($products as $product)
<div class="product">
<a href="store/view/{{ $product->id }}">
{{ HTML::image($product->image , $product->title , array('class'=>'feature' ,
'width'=>'240' , 'height'=>'127')) }}
</a>
<h3>
<a href="/store/view/{{ $product->id }}">
{{ $product->title }}
</a>
</h3>
<p>
{{ $product->description }}
</p>
<h5>Availability:
<span class="{{ Availability::displayClass($product->availability) }}">
{{ Availability::display($product->availability) }}
</span>
</h5>
<p>
<a href="#" class="cart-btn">
<span class="price">${{ $product->price }}</span>
{{ HTML::image('img/white-cart.gif' , 'Add to Cart') }}
ADD TO CART
</a>
</p>
</div>
#endforeach
</div> <!-- end products -->
#stop
In my storeController , i am calling the store/index.blade.php file like so:
public function getIndex() {
return View::make('store.index')
->with('products' , Product::take(4)->orderBy('created_at' , 'DESC')->get());
}
In my routing file, i have the following:
Route::get('/', array('uses' => 'StoreController#getIndex'));
But still when i load my / , i get some other template rather than layouts/main.blade.php. Why is this happening ? can anybody explain ?
Why is layouts/main.blade.php not loading when i hit / in the browser ?
Thank you.
Alex-z.
Well i had the following syntax .
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
{{ HTML::style('css/bootstrap.css') }}
{{ HTML::style('css/animate.min.css') }}
{{ HTML::style('css/style.css') }}
{{ HTML::style('css/nprogress.css') }}
{{ HTML::style('css/new-arrivals.css') }}
Removing the below line
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
solved my problem ... Why though ? also how do i disable cache in laravel during development ?

laravel/blade cycle in template

I need your help. Here is my template file. How can I make to work that template? Main problem is that I don't know how to change div class values. Now I can make working only <div class="thumb-left"> but I also need <div class="thumb-middle"> and <div class="thumb-right">.
Thank you.
#extends('_layouts.main')
#section('content')
<div id="content-section">
#foreach ($uploads as $upload)
<div class="thumb-left">
<img alt="{{ $upload->image_title }}" title="{{ $upload->image_title }}" src="/files/images/{{ $upload->imagefile }}" height="250" width="300">
<div class="thumb-info">
{{ $upload->image_title }}
<a class="cat" href="#">PHOTOS</a>
</div>
</div>
#endforeach
<div class="thumb-middle">
<img alt="sunset" title="Sunset HDR" src="img/thumb.jpg" height="250" width="300">
<div class="thumb-info">
{{ $upload->image_title }}
<a class="cat" href="#">PHOTOS</a>
</div>
</div>
<div class="thumb-right">
<img alt="sunset" title="Sunset HDR" src="img/thumb.jpg">
<div class="thumb-info">
City Sunset HDR
<a class="cat" href="#">PHOTOS</a>
</div>
</div>
</div>
#stop
You could do:
#foreach ($uploads as $upload)
<div class="thumb-{{ array('left', 'middle', 'right')[($loop->iteration-1)%3] }}">
<img alt="{{ $upload->image_title }}" title="{{ $upload->image_title }}" src="/files/images/{{ $upload->imagefile }}" height="250" width="300">
<div class="thumb-info">
{{ $upload->image_title }}
<a class="cat" href="#">PHOTOS</a>
</div>
</div>
#endforeach
The $loop variable is a build in blades variable - check the docs:
When looping, a $loop variable will be available inside of your loop.
This variable provides access to some useful bits of information such
as the current loop index and whether this is the first or last
iteration through the loop. For instance: $loop->iteration - the current loop
iteration (it starts at 1).
You probably want to change your foreach to also use a key, so you can know at which index in your array you are:
<div id="content-section">
#foreach ($uploads as $index => $upload)
<div class="thumb-left">
<img alt="{{ $upload->image_title }}" title="{{ $upload->image_title }}" src="/files/images/{{ $upload->imagefile }}" height="250" width="300">
<div class="thumb-info">
{{ $upload->image_title }}
<a class="cat" href="#">PHOTOS</a>
</div>
</div>
#endforeach
</div>
Now, if I understand properly, what you're looking for is to switch from thumb-left, to thumb-middle and then finally thumb-right, and then loop again. You could use modulo to assign your class name based on the current index. This is untested code but you could probably use something along the lines of:
<div id="content-section">
{{ $classnames = array("thumb-left", "thumb-middle", "thumb-right"); }}
#foreach ($uploads as $index => $upload)
<div class="{{ $classnames[$index % count($classnames)] }}">
<img alt="{{ $upload->image_title }}" title="{{ $upload->image_title }}" src="/files/images/{{ $upload->imagefile }}" height="250" width="300">
<div class="thumb-info">
{{ $upload->image_title }}
<a class="cat" href="#">PHOTOS</a>
</div>
</div>
#endforeach
</div>

pyrocms assign count to variable

I would like to check if is last post from loop. I am using pyroCMS. But problem is that if i am using helper:count two times it is not working correctly. How can i assign helper:count to variable and use later variable. Is this possible?
{{ blog:posts limit="5" order-by="title" order-dir="desc" }}
{{ if { helper:count mode="subtract" } == blog:all_posts}}
<li>
<a href="{{ url }}" title="Read more about: {{ title }}">
<span class="naslovna_datum_novice">{{ helper:date format="d.m.Y" timestamp=created_on }} - </span>
{{ title }}
</a>
</li>
{{ elseif { helper:count mode="subtract" } == 5 }}
<li>
<a href="{{ url }}" title="Read more about: {{ title }}">
<span class="naslovna_datum_novice">{{ helper:date format="d.m.Y" timestamp=created_on }} - </span>
{{ title }}
</a>
</li>
{{ else }}
<li class="pikce_spodaj">
<p>
<a href="{{ url }}" title="Read more about: {{ title }}">
<span class="naslovna_datum_novice">{{ helper:date format="d.m.Y" timestamp=created_on }} - </span>
{{ title }}
</a>
</p>
</li>
{{ endif }}
{{ /blog:posts }}
So how to assign {{ helper:count mode="subtract" }} to variable?? How to assign anything to variable?
There's actually a simpler way; the streams core code adds a last property to the final item in an array - source code - that you can just query with a conditional:
{{ if last }} foo {{ endif }}
(The source code that does that is
Here's a working example for blogs I've just tested:
{{ blog:posts limit="5" order_by="title" }}
<h2>{{ title }}</h2>
[...]
{{ if last }}<p>This is the last item</p>{{ endif }}
{{ /blog:posts }}
Also, as Nick points out, you can have more than one counter.

Categories