Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A smart way to hide any element from any view in Laravel 5.3?

I am facing a problem where I don't want to display an X element in some views.

The real example is that I don't want to show product image slider on pages contact and about us, but it should be visible on all other pages (about 6 more)

So how to exclude rendering the div in n of m pages without making very long @if conditions? Any idea for stylish solution?

Edit Answering the question why I don't want to put this in standalone view file:
Imagine that you want this line to be visible in all views your views except specific one, and only one

<span>Lorem Ipsum</span>

This is just a single line of HTML code, it's not worth to create another file in project because it will be a mess in project files tree, and another example that is a bad workaround

@if(\Request::route()->getName() !== "some.very.long.route.alias.name.that.looks.ugly")
    <span>Lorem Ipsum</span>
@endif

Makes code hard to read and understand when project grows

Edit 2 I predicted some of suggested solutions and already wrote why this is not suitable way to handle this. I am looking more likely for a solution that is similar to @can or @cannot that depends on current route

Edit 3: Working on solution

Edit 4: I posted an answer here but it's not perfect yet (I won't mark it as accepted yet), so just for readers of this topic I will paste the copy of it below

Ok I have made a simple blade directive that solves this case in a well-looking way

At first, create an array that determines route access for html snippet
Best place would be to create this file in config directory, on example a presence.php file

<?php
return [
    'ipsum' => [            // presence alias
        'about',            // disallowed route #1
        'contact'           // disallowed route #2
    ],
];

Then create a directive in AppServiceProvider.php class

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Blade::directive('presence', function($alias) {
            return "<?php if (in_array(\Request::route()->getName(),config('presence.'.$alias))):?>";
        });

        Blade::directive('endpresence', function() {
            return '<?php endif; ?>';
        });
    }

    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

And in the final usage of this trick in html view

@presence('ipsum')
    <span>Lorem Ipsum</span>
@endpresence

It will print Lorem Ipsum if the current route name is not in ipsum array (which is declared in \App\config\presence.php file so we can access it with config() helper method)

It would be great if I could handle wildcard characters, like

<?php
return [
    'ipsum' => [            // presence alias
        'admin.category.*',       // advanced route pattern #1
        'admin.users.*'           // advanced route pattern #2
    ],
];

But I will look into it later.

Feedback, or criticism is always welcome :)

like image 793
Bartłomiej Sobieszek Avatar asked Oct 29 '22 18:10

Bartłomiej Sobieszek


2 Answers

If contact and about us have their own URIs, you can try to match on that to determine if you should show the element of not...

if (!\Request::is('contact') && !\Request::is('about-us')) {
    // Show element X
}

Or another way to do it would be to add a middleware which sets some variable, for example $dontShowElement and sets up a view composer and passes that variable to all views. Then all you need to do is check for the existence of that variable before outputting the element and only give those 2 routes you want that element to be hidden on that middleware.

like image 157
user1669496 Avatar answered Nov 01 '22 15:11

user1669496


If you are using blade templating, you could create two different layouts. One with the image slider and one without. This is the most straightforward solution I can think up from the top of my head.

EDIT: Creating another layout, especially if you have all your layouts in a separate folder, will not create a mess in the file structure and it will definitely be worth it.

like image 20
yarwest Avatar answered Nov 01 '22 16:11

yarwest