Git Product home page Git Product logo

laravel-menu's Introduction

Html Menu Generator for Laravel

Latest Version on Packagist Software License Test Status Code Style Status Total Downloads

This is the Laravel version of our menu package adds some extras like convenience methods for generating URLs and macros.

Documentation is available at https://spatie.be/docs/menu.

Upgrading from version 1? There's a guide for that!

Menu::macro('main', function () {
    return Menu::new()
        ->action('HomeController@index', 'Home')
        ->action('AboutController@index', 'About')
        ->action('ContactController@index', 'Contact')
        ->setActiveFromRequest();
});
<nav class="navigation">
    {!! Menu::main() !!}
</nav>

Spatie is a webdesign agency based in Antwerp, Belgium. You'll find an overview of all our open source projects on our website.

Support us

We invest a lot of resources into creating best in class open source packages. You can support us by buying one of our paid products.

We highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using. You'll find our address on our contact page. We publish all received postcards on our virtual postcard wall.

Installation

You can install the package via composer:

composer require spatie/laravel-menu

Usage

Documentation is available at https://spatie.be/docs/menu.

Changelog

Please see CHANGELOG for more information what has changed recently.

Testing

$ phpunit

Contributing

Please see CONTRIBUTING for details.

Security

If you've found a bug regarding security please mail [email protected] instead of using the issue tracker.

Credits

License

The MIT License (MIT). Please see License File for more information.

laravel-menu's People

Contributors

adrianmrn avatar akoepcke avatar alexvanderbist avatar ansien avatar ayoobmh avatar ccsliinc avatar cretueusebiu avatar erikn69 avatar francoism90 avatar freekmurze avatar ignaciocastro0713 avatar laravel-shift avatar masterbratac avatar nielsvanpach avatar omranic avatar patinthehat avatar sebastiandedeyne avatar smart-one avatar vmitchell85 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

laravel-menu's Issues

Adding a class to each li

Hi,

I've looked through the docs and seen how to add classes to the ul and the a but not the li.

Bootstrap has nav-item on the li and I can't seem to work out how to add that within the ->route() items.

Menu::macro('main', function() {
    $menu = Menu::new()
        ->addClass('navbar-nav mr-auto')
        ->addItemClass('nav-link')
        ->route('candidates.index', 'Candidates')
        ->route('requisitions.index', 'Requisitions')
        ->route('accounts.index', 'Accounts')
        ->route('contacts.index', 'Contacts')
        ->setActiveFromRequest()
        ;

    return $menu;
});

Which generates

<ul class="navbar-nav mr-auto">
    <li>
        <a href="https://domain.dev/candidates" class="nav-link">Candidates</a>
    </li>
    <li class="active">
        <a href="https://domain.dev/requisitions" class="nav-link">Requisitions</a>
    </li>
    <li>
        <a href="https://domain.dev/accounts" class="nav-link">Accounts</a>
    </li>
    <li>
        <a href="https://domain.dev/contacts" class="nav-link">Contacts</a>
    </li>
</ul>

but I need this on each item

<li class="nav-item">

Thanks!

[PROPOSAL] AddArray method

Hey,

as I am starting to use the package, it noticed that it would be pretty handy to be able to loop over an array. Pretty often menu items will be stored in a config file or a database and retrieved in one set. While it is possible to achieve this by hand or using a macro, I think it would be a valuable addition to the package (probably added to the main package, nor the Laravel version).

To allow for as much flexibility and little code, I would suggest to add a method that takes an array and a callable as parameters, the callable gets the $key and $value and needs to return an Item.

I used the macro function to build a "prototype" but I think it would be much better to include this into the default build.

Menu::macro('addArray', function(array $array, callable $callable){
    foreach($array as $key => $value)
    {
        $this->add($callable($value, $key));
    }
    return $this;
});

// will be use like this:

return Menu::new()
    ->addArray([
        [
            'link' => '/link',
            'name' => 'Link'
        ],
        [
            'link' => '/link-2',
            'name' => '2nd Link'
        ],
    ], function($item){
        return Link::to($item['link'], $item['name']);
    });

Where is the so-called 'View'?

Menu::new()
    ->add(View::create('greeting', ['name' => 'Sebastian', 'url' => '/profile']))
    ->setActiveFromUrl('/profile');

Error:

ErrorException in Facade.php line 237:
Call to undefined method Illuminate\View\Factory::create() (View: C:\xampp\htdocs\fc_project_a\resources\views\layouts\menu.blade.php) (View: C:\xampp\htdocs\fc_project_a\resources\views\layouts\menu.blade.php) (View: C:\xampp\htdocs\fc_project_a\resources\views\layouts\menu.blade.php) (View: C:\xampp\htdocs\fc_project_a\resources\views\layouts\menu.blade.php)

[Feature Request] Allow Blade inside link names

I'm proposing this feature request for allowing the inclusion and therefore procesing of blade inside link titles, if at all possible. For example, try combining this with @adamwathan's blade-svg project. You'd get something like this in your code..

 Menu::macro('main_logged_in', function () {
            return Menu::new()
                ->route('home', '@svg("folder-outline") Decks')
                ->route('home', '@svg("buoy") Support')
                ->setActiveFromRequest();
 });

Unfortunately, here Adam's package stops working, since the blade syntax is not being processed anymore. What comes out is this

the result

What I'd really like is for the svg's to be displayed from Adam's package, and therefore possibly any other blade to be allowed to be in titles.

[L5.7] setActiveFromRequest() throws Exception after 'php artisan config:cache'

Hi,

Today I observed that after running php artisan optimize, the method setActiveFromRequest() will throw an ErrorException: array_merge(): Argument #1 is not an array.

Using Laravel Telescope, I found that it is the spatie/url package, method fromString that does that array_merge(), using a parse_url() function that ends up not returning an array.

After running php artisan optimize:clear the exception goes away and everything is back to normal.

Through some trial and error, I was able to track it down to php artisan config:cache that is causing the interference.

I am currently running the following versions:

spatie/laravel-menu                 3.2.1           Html menu generator for Laravel
spatie/menu                         2.8.0           Html menu generator
spatie/url                          1.3.0           Parse, build and manipulate URL's

I believe those are the current releases.

I am not sure if this is the right place for this issue, but since spatie/url was installed as a dependency of spatie/menu and ultimately spatie/laravel-menu, I figured that this was a place to start.

I am also not sure why that config:cache is interfering with the urls?

Anyway, if you need more information, let me know.

Set `a class` to active, rather than `li class`

Is it possible to setup a menu as per title? Bootstrap 4's pill navigation uses active differently to what's usually used, and sets active as part of the a attribute instead of the li attribute.

Views for generating menu

Would it be possible that the whole code that generates the menu output could be put into views?

This makes it easier to customize, and then it could support parsing custom views in while outputting the menu as HTML, then it will use the view parsed to it.

class to linkIfCan

Hi!
I'm trying to set a class for the link on the linkIfCan but I'm stuck.

            ->linkIfCan('propietario-list',route('propietarios.index'),'Propietarios')                
            ->add(Link::to('/ofertas', 'Ofertas')->addClass('nav-link'))

[Feature Request] Add items to tagged positions

Dear Spatie team,

First of all thank you for all your hard work 👏.

I've been playing with laravel-menu for a bit now and figured out how to add items to the same menu from various sources:

  • I added a 'test' link from within the Laravel app
  • I added a 'package' link from within a custom Laravel package

I'm wondering if it would be useful, and in the scope of this package, to be able to add a menu item to a tagged position.

Painting a picture: let's say you are building your own docs sidebar menu. You could optionally "tag" a position called "Basic Usage". From anywhere in your code you could fetch your menu with app('menu.docs.sidebar) (pseudo-code) and ->link('random-link', 'Random Link');. This would prepend the "Random Link" item to the sidebar menu, specifically under the "Basic Usage" list.

If this is already possible I've must've skipped the docs on that part. If this is not possible, I'd love to collaborate on the solution and possibly provide a Pull Request, if and when required.

Thank you for looking into this, and I'd love hearing from you.

Tom

route() method has only 3 args, 4 passed.

Hi guys,
on your $menu->route() method, you consider 4 arguments, but at the end the \Illuminate\Routing\UrlGenerator::route accept only three.

Am I missing something, or the last parameter \Illuminate\Routing\Route $route is useless?

Thanks.
Matt'

screen shot 2017-02-17 at 18 59 10

screen shot 2017-02-17 at 18 57 19

setActiveFromRequest: Return true on "child" urls

Hi there,

I got these routes:

  • user.index
  • user.show
  • user.create

Is it possible that on

Menu::macro('aside', function () {
            return Menu::new()
                ->setActiveClass('active')
                ->addClass('nav nav-default nav-parent-icon')
                ->setAttribute('data-nav')
                ->link(route('home'),
                    Html::raw("<span data-icon=\"icon: home\" class=\"margin-small-right\"></span>")
                        ->render()." Home")
                ->linkif((auth()->user()),route('user.index'),
                    Html::raw("<span data-icon=\"icon: users\" class=\"margin-small-right\"></span>")
                        ->render()." Benutzer")
                ->linkif((auth()->user()),route('blog.index'),
                    Html::raw("<span data-icon=\"icon: blog\" class=\"margin-small-right\"></span>")
                        ->render()." Blog")
    
                ->setActiveFromRequest();
        });

this part:

->linkif((auth()->user()),route('user.index'),
                    Html::raw("<span data-icon=\"icon: users\" class=\"margin-small-right\"></span>")
                        ->render()." Benutzer")

Is active on all of the three routes (index, show, create)?

Need Example for Recrusive Menu.

I am stuck when try to create recrusive menu from Laravel Collection.

For Example I Have 'Menu Table'

id | title | parent_id
1 | A | null,
2 | B | 1
3 | C | 1
4 | D | 3
5 | E | 3
6 | F | null,

Thanks for

Problem with subroutes?

Hi,

I'm building a blog category menu.
So I have;
All - Travel - Sleeping - and so on

The route of All is /blog
The route of Travel is /blog/category/travel

If I'm visiting the /blog URL only the All category contains the class "Active".
If I'm on /blog/category/travel is adds the class active to both All and Travel.

I've tried using setActiveFromRequest as well as setActive(url()->full()) but both give the same outcome.

If I change the slug of my named route (/blog) to /blogs the issue is gone.
Basically it looks like the code is match if the nav item URL is in the URL instead of if it is the the URL.

How do I add menu items after the object is built?

I've registered my menu in a service provider like below (and as described in #52), and I'm able to use it my views without issues.
Menu::macro('main', function () { return Menu::new() ->add(Link::to('/', 'Home')) ->add(Link::to('/about', 'About')); });

However, if I'm adding items to the menu afterwards, let's say from a controller, it doesn't seem to add the items (and it's not giving me any error either). Here's the code I'm using in my controller:
Menu::main()->add(Link::to('/contact', 'Contact'));

Any idea how to add items to the menu after the object is built?

**[QUESTION]**: How do I display the menu on the blade template?

In raising this issue, I confirm the following (please check boxes):

  • I have read and understood the contributors guide.
  • I have checked the pull requests tab for existing solutions/implementations to my issue/suggestion.
  • I have checked that the bug-fix I am reporting can be replicated.

How do I display the menu on the blade template?

I am trying to show the menu on the layout template after I built it using View Composer. This is the code I have in resources/views/layout.blade.php:

<nav class="navigation">
    {!! Menu::main() !!}
</nav> 

And I got this error:

ErrorException in Macroable.php line 81:
Method main does not exist. (View: /var/www/html/platform.local/resources/views/layout.blade.php) (View: /var/www/html/platform.local/resources/views/layout.blade.php)

I don't know if I am missing something here but is not working and I can't find in docs an example of this. If needed this is the repository I am working with and below is a list of the classes involve:

Can you give me some help? Maybe improve docs for newbies?

Steps to reproduce

Just clone the repository, run the migrations and seeds and try to open the page you should see the issue.

Wrap around <ul> only

Got pretty much everything working. Thanks for the package!

One small issue with dropdown using UIKit. When I use ->submenuIf() and have ->wrap('div', ['class' => 'uk-navbar-dropdown']), it adds it around the <a> as well which I don't want. Any way to do that? Tried quite a few different ideas but none worked.

Menu::macro('main', function() {
    $menu = Menu::new()
        ->addClass('uk-navbar-nav')
        ->setActiveClass('uk-active')
        ->route('home', 'Home')
        ->submenuIf($isAdmin, '<a href="#">Admin</a>', function (Spatie\Menu\Laravel\Menu $menu) {
            $menu
                //->wrap('div', ['class' => 'uk-navbar-dropdown'])
                ->addClass('uk-nav uk-navbar-dropdown-nav')
                ->route('admin.item', 'Item')
                ->route('admin.item2', 'Item 2')
            ;
        })
        ->setActiveFromRequest()
    ;

    return $menu;
});

Need this format;

<li>
    <a href="#">Parent</a>
    <div class="uk-navbar-dropdown">
        <ul class="uk-nav uk-navbar-dropdown-nav">
            <li><a href="#">Item</a></li>
            <li><a href="#">Item</a></li>
        </ul>
    </div>
</li>

[Feature Request] Set SubmenuHeader Active if it's the active link

When the active site is the SubmenuHeader, the li before the Link (and the path before) doesn't be set as active.
The same behavior can be noticed when the SubmenuHeader is a view...

It would solve a lot of my problems, if this would be added.

Use Case:

Menu::new()
    ->submenu(
        Link::toRoute('routename', ''Link-Title'),
        Menu::new()
    )
    ->submenu(
        View::create('viewname', ['title' => 'Link-Title', 'url' => route('routename')]),
        Menu::new()
    )

[Question] How to add Link with Form

Is there any way to add a Menu Item that also contains a form that would be used by clicking on the menu item? Something like the following.

<li>
    <a onclick="event.preventDefault();document.getElementById('logout-form').submit();">
        @lang('logout')
    </a>

    <form id="logout-form" action="{{ route('logout') }}" method="DELETE" style="display: none;">
        {{ csrf_field() }}
    </form>
</li>

addif processing even if condition fails [laravel 5.6]

In my Laravel 5.6 MenuService provider I have this offending line:

->addif(Auth::check(), Link::to('/profile/'.Auth::user()->id, '<i class="fas fa-user-cog mr-2"></i>Profile'))->addItemClass('nav-link')

I am currently getting this error: Trying to get property of non-object
This tells me, that even though Auth::check() is false, the link is still trying to be populated. Am I using addIf() wrong, or is this intended behaviour? If this is intended, what can I use for the menu to check for logged in, and if true render the link, otherwise ignore the link?

Thanks for making a great package. This has been really useful! :)

Change Menu::new() function name

For my PHP obfuscator and linter it would be better if the static functions of the Menu class were not called "new()". Can you please rename them for future versions?

Horizontal, Vertical and multilevel menu

How can we customize the menu setting like horizontal, vertical and multisteps menu as dynamic content, as well from horizontal menu to vertical in multistep menu?

->setActiveFromRequest() not working with relative urls

Hi!

I've just installed laravel-menu and I really like it. One thing that doesn't work is the setActiveFromRequest() method, as it's comparing to full url to relative paths in my Laravel instance.

Code:

Menu::new()
    ->addClass('nav navbar-nav navbar-right')
    ->link('/', 'Home')
    ->link('/faq', 'FAQ')
    ->link('/contact', 'Contact')
    ->setActiveFromRequest()

When accessign http://local.dev/faq no menu item is set to active. Same for contact.

I tried debugging the code and got into this method inside the spatie/menu package:

/**
     * @param string $url
     * @param string $root
     *
     * @return $this
     */
    public function determineActiveForUrl(string $url, string $root = '/')
    {
        if (! $this->hasUrl()) {
            return;
        }
        $itemUrl = Url::fromString($this->url);
        $matchUrl = Url::fromString($url);
        // If the hosts don't match, this url isn't active.
        if ($itemUrl->getHost() !== $matchUrl->getHost()) {
            return $this->setInactive();
        }
        // If this url doesn't start with the root, it's inactive.
        if (! Str::startsWith($itemUrl->getPath(), $root)) {
            return $this->setInactive();
        }
        // For the next comparisons we just need the paths, and we'll remove
        // the root first.
        $itemPath = Str::removeFromStart($root, $itemUrl->getPath());
        $matchPath = Str::removeFromStart($root, $matchUrl->getPath());
        // If this url starts with the url we're matching with, it's active.
        if (Str::startsWith($matchPath, $itemPath)) {
            return $this->setActive();
        }
        return $this->setInactive();
    }

The first if inside the method is matched, as the itemUrl does not have a host but the matchUrl does.

For example:

itemUrl: /faq
matchUrl: http://local.dev/faq

Is there anything that I can do to make the method match only for the path and not the host?

Laravel version: 5.3.29
PHP version: 7.0.13

[QUESTION] Setting up menu with Laravel-permissions

Hello,

First of all thanks for all the open source packages you guys provide us, I am having a bit of a problem with the LinkIfCan method when using https://github.com/spatie/laravel-permission . I have the following.

Please note that the permissions for a user are via a role. If i check the gates they are registered.

In a Service provider loaded after the laravel permissions and laravel menu ones

protected function registerMenus()
{
    $this->app->singleton('menu.sidebar', function(){
        return app(Menu::class)->addClass('sidebar-menu');
    });
}

Then in another service provider I have

protected function setMenu()
{
    $menu = app('menu.sidebar');
    $menu->add(Html::raw('<li class="header">USUARIOS</li>'));
    $menu->linkIfCan('Listar Usuarios', '/users', 'Listar');
}

The item won't show up even if the user has the permission assigned and registered in the Gate.

I went to https://github.com/spatie/laravel-menu/blob/master/src/Menu.php#L152 and this (app(Gate::class)->allows($ability, $ablityArguments) returns false, but if I run that same line in a controller changing $ability by the permission it returns true, so I am lost on that one :(

Any help is very appreciated

Thanks!

Link :: to fail

When I try to use Link :: to fail

Laravel 5.4
Php 7

(2/2) ErrorException
Class 'Link' not found

I use this example

Menu::new()
    ->addClass('nav navbar-nav')
    ->link('/one', 'One')
    ->link('/two', 'Two')
    ->submenu(
        Link::to('#', 'Dropdown <span class="caret"></span>')
            ->addClass('dropdown-toggle')
            ->setAttributes(['data-toggle' => 'dropdown', 'role' => 'button']),
        Menu::new()
            ->addClass('dropdown-menu')
            ->link('#', 'Action')
            ->link('#', 'Another action')
            ->html('', ['role' => 'separator', 'class' => 'divider'])
    )
    ->wrap('div.collapse.navbar-collapse')
    ->setActive('/one');


Subpage url() activation in multiple menus.

Given a use case as such:

Menu::macro('self_service', function () {
    return Menu::new()
        ->prepend('<b>KASUTAJA</b>')
        ->url('/ise', 'Ülevaade')
        ->setActiveFromRequest();                
});

Menu::macro('association_admin', function () {
    return Menu::new()
         ->prepend('<b>KORTERÜHISTU</b>')
         ->url('/ise/yhistu/korterid', 'Korterid')                           
         ->setActiveFromRequest();                
});

where the first menu is always rendered, and the second one lives inside an if statement, when going to /ise/yhistu/korterid', the link for /ise in the first menu gets activated aswell. This is not wanted, is there a way to prevent this?

Installation problem

I installed the plugin with composer, then added the provider and the facade. However, I still get an error

Class 'Menu' not found (View: /path/to/laravel/views/layouts/menu.blade.php

I added this to the providers array

Spatie\Menu\Laravel\MenuServiceProvider::class

And I added this to the aliasses array

'Menu' => Spatie\Menu\Laravel\MenuFacade::class

I am also using Barry's LaravelIdeHelper, which also does not pick up on the Menu class. I am unsure what I did wrong. Other plugins did install without problems and this time I did not do anything different. I already tried using an older version.

This is my composer.json

    "require": {
        "php": ">=5.6.4",
        "barryvdh/laravel-debugbar": "^2.3",
        "barryvdh/laravel-ide-helper": "^2.2",
        "laracasts/utilities": "~2.0",
        "laravel/framework": "5.4.*",
        "laravel/tinker": "~1.0",
        "spatie/laravel-menu": "~2.1.2"
    },

Bootstrap 4

Thanks for this package :)

Are there plans to update it to accommodate the slightly different menu structure in Bootstrap 4?

The sub menu child item cannot be activated

Menu::new()
->add(...)
->submenu(
                        Menu::new()
                            ->prepend('<a data-toggle="collapse" href="#safety_management"><i class="ti-lock"></i><p>安全管理<b class="caret"></b></p></a>')
                            ->addClass('collapse nav')
                            ->setAttribute('id', 'safety_management')
                            ->link('/user/change-password', '<span class="sidebar-mini">&nbsp;</span><span class="sidebar-normal">修改密码</span>')
//                            ->setActive('/user/change-password')   //running
                            ->setActive(function (Link $link) {
                               dd($link);    //Not running           

                                return $link->url() === explode('?', Request::getRequestUri())[0];
                            })
                    )

Route not defined in Laravel 5.5

Hi, I installed this package in my app, where I use routes by name, but when I use route method to create a item in menu, occurred a error.

Is compatible with version 5.5?

Menu::create method doesn't exist.

Can't install this package. Did someone had a problem like this one?
In Macroable.php line 99:
Method Spatie\Menu\Laravel\Menu::create does not exist.

[PROPOSAL] AddView

I did not find an easy way to add a view to the menu.

I am thinking about using this package and I have some more complicated menu items, that are more than just a link. I store those items in separate views, which is why adding a view as a menu item would be good.

Maybe something like this:

Menu::new()
  ->action('HomeController@index', 'Home')
  ->addView('menu.viewFile', $viewData);

I think currently it would be possible to pass a view('menu.viewFile', $viewData)->render() to the add() method? But I think this would be a nicer way to add it.

Of course I just realise, that setActiveFromRequest would not work with a rendered view, would it? This would possible make it even more useful, as some logic for this could be included.

Class 'Link' not found

Hi,

I use laravel 5.6 and when trying to generate a menu, I get a "Class 'Link' not found error".
This is working:
echo Menu::new()->link('/', 'Home')->render();

This is not with error "Class 'Link' not found":
echo Menu::new()->add(Link::to('/about', 'About'))->render();

Stef

[QUESTION] Bootstrap-style submenu's

  • I have read and understood the contributors guide.
  • I have checked the pull requests tab for existing solutions/implementations to my issue/suggestion.
  • I have checked that the bug-fix I am reporting can be replicated.

Description of the problem

I am struggling to get submenu's working with Bootstrap 3 navbar's. It simply boils down to this: the examples you provide generate submenu's in a separate <li>, while Bootstrap expects you to add a submenu right after the anchor, within the same <li> of the parent.

Laravel-menu generates:

<ul>
    <li>
        <a href="/">Menu</a>
    </li>
    <li>
        <ul>
            <li>
                <a href="/basic-usage/your-first-menu">Your First Menu</a>
            </li>
        </ul>
    </li>
</ul>

While Bootstrap expects:

<ul>
    <li>
        <a href="/">Menu</a>
        <ul>
            <li>
                <a href="/basic-usage/your-first-menu">Your First Menu</a>
            </li>
        </ul>
    </li>
</ul>

In order to generate the second code fragment using laravel-menu, I would expect something like this in PHP:

Menu::new()->add(Link::to('/', 'item'), Menu::new()
    ->add(Link::to('/sub', 'subitem'))
);

Is there something I missed? Or are there any plans in making this work, making Bootstrap submenu's possible?

Steps to reproduce

I have used the submenu code examples from the documentation.

Replace string text with optional callback

Dear Spatie team,

I'd love to get more control of the render method on the Link class. At the moment I'm working with a menu structure that I can not replicate with this package. Would it be in the scope of this package to allow for a callback that will format the string to be returned via the aforementioned render method?

I'd love to work on a PR and get your feedback.

Tom

Installation problem

run: composer require spatie/laravel-menu

Found Error
[InvalidArgumentException]
Could not find package spatie/laravel-menu at any version for your minimum-
stability (stable). Check the package spelling or your minimum-stability

[QUESTION] Add menu items in different modules

Hello,

I have a question. Currently I use modules to make my application more encapsulated.

For example I have to following modules

  • Core
  • Page
  • User
  • Settings

Now I want that my backend menu is more flexibel. So I want to add menu points via service provider of the modul.

I create the menu within the "Core"-Modul.
Can u help me, how I can do that ?

Greetings.

Add activateForPath method

Hey @sebastiandedeyne,

as you might have noticed, I am using views for all my menu items. While I understand that this might not be the case for your projects, I think it is a very likely case for things like:

  • profile links with (img) Name
  • links prefixed with an inline/use svg
  • links which have Additional elements, e.g. a list of links with a delete link on them as well

... and many more.

I do understand you do not want to alter and/or mess up the api, so something like View::create('/link','view.name') is out of the question.

My proposal would be to add a function activateForPath which could be used to set the link that should trigger the activation of a menu item.

The usage would be like this:

View::create('view.name')->activateForPath('/link');

I think, all it would need to do would be the following:

public function activateForPath($path)
{
    if(app('request')->path() === trim($path,'/')){
        $this->setActive();
    }

    return $this;
}

This would solve such a big headache, please, let us implement it. 😃

[PROPOSAL] add hasUrl to HTML

Hey,

I think it would make sense to add the hasUrl interface to HTML objects as well. This would mean they can be automatically activated by the menu. Realistically every menu item that is not a simple link will be some form of HTML or HTML-like (#9) object. This however does not mean that those objects to not have a link. They probably do and need to be activated just like link objects.

The main issue is, that this requires a change in the Interface, as it means that a $url with a value of null must be accepted, to indicate no link is present (for cases where adding html does not mean adding a link).

When null is present the interface would need to understand that it should not do the link stuff.

Once this is taken care of, implementing it should be very easy.

To try it out I extended the class like this. I needed to fake a bit and use the string 'null'. To get it to work. However this would actually activate any that is supposed to not have a link, when the url /null is active.

class spatieHTML extends HTML implements HasUrl{

     protected $prefixes = [];
     protected $url = [];

    protected function __construct(string $html, string $url = null)
    {
        $this->html = $html;
        $this->url = $url;
        $this->active = false;
        $this->initializeParentAttributes();
    }

    public static function raw(string $html, string $url = 'null')
    {
        return new static($html, $url);
    }

    public function getUrl(): string
   {
       if (empty($this->prefixes)) {
           return $this->url;
       }
       return implode('', $this->prefixes) . '/' . ltrim($this->url, '/');
   }

   public function segment(int $index)
   {
       $path = parse_url($this->url)['path'] ?? '';
       $segments = array_values(
           array_filter(
               explode('/', $path),
               function ($value) {
                   return $value !== '';
               }
           )
       );
       return $segments[$index - 1] ?? null;
   }
   /**
    * @param string $prefix
    *
    * @return $this
    */
   public function prefix(string $prefix)
   {
       $this->prefixes[] = $prefix;
       return $this;
   }

}

Now using it would be pretty easy:

Menu::new()
    ->add(spatieHTML::raw(view('menu.item', $item)->render()), '/link')
    ->add(spatieHTML::raw(view('menu.notAnItem', $item)->render()));

Additionally the prefixLinks method would have to be adapted to not typehint Link. Alternatively a new method like prefixItemLinks could be created, that is basically a copy of prefixLinks just without the typehint.

How to use a generated menu in all views

Hi there,
new to Laravel (5.4)

I've created a basic menu.
To test, I placed the code in my HomeController but obviously rendering only works in the view called in the controller.

My blade structure is as follow
home.blade -> @extends('layouts.blank')
blank.blade -> @include('includes/sidebar')
sidebar.blade -> contains {!! Menu::main() !!}

So when I'm using home I can see the menu but any other view that extends blank doesn't render the menu.

Where can I use a basic menu defined like that

$menu = Menu::new([
    Link::to('/', 'Home'),
    Link::to('/about', 'About'),
]);

and have it available in all views?
Probably a service controller or a middleware but to be honest since I'm new to Laravel I don't have a clue.

Thanks.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.