Having Fun with the Menu
Keep on Learning!
If you liked what you've learned so far, dive in! Subscribe to get access to this tutorial plus video, code and script downloads.
With a Subscription, click any sentence in the script to jump to that part of the video!
Login SubscribeOur menu on the left is getting a little long and... kind of confusing... since we now have two question links. To make this more user-friendly, let's divide this into a sub-menu. We do that inside of DashboardController... because that's, of course, where we configure the menu items.
Adding a Sub Menu
To create a sub-menu, say yield MenuItem::subMenu() and then give that a name - like Questions - and an icon... just like we do with normal menu items.
To populate the items in this menu, say ->setSubItems(), pass this an array, and then we'll wrap our other two menu item objects inside of this. Of course, now we need to indent, remove the yield, and... replace the semicolons with commas.
Perfect! Now change Questions to... how about All... and let's play with the icons. Change the first to fa fa-list... and the second to fa fa-warning.
| // ... lines 1 - 24 | |
| class DashboardController extends AbstractDashboardController | |
| { | |
| // ... lines 27 - 57 | |
| public function configureMenuItems(): iterable | |
| { | |
| // ... line 60 | |
| yield MenuItem::subMenu('Questions', 'fa fa-question-circle') | |
| ->setSubItems([ | |
| MenuItem::linkToCrud('All', 'fa fa-list', Question::class) | |
| ->setController(QuestionCrudController::class) | |
| ->setPermission('ROLE_MODERATOR'), | |
| MenuItem::linkToCrud('Pending Approval', 'fa fa-warning', Question::class) | |
| ->setPermission('ROLE_MODERATOR') | |
| ->setController(QuestionPendingApprovalCrudController::class), | |
| ]); | |
| // ... lines 70 - 73 | |
| } | |
| // ... lines 75 - 134 | |
| } |
Let's try that. Move over... refresh and... ahhh, much cleaner!
Menu Sections
But wait, there's more we can do with the menu... like adding separators... technically called "sections". Right after linkToDashboard(), add yield MenuItem::section() and pass it Content.
| // ... lines 1 - 57 | |
| public function configureMenuItems(): iterable | |
| { | |
| // ... line 60 | |
| yield MenuItem::section('Content'); | |
| // ... lines 62 - 75 | |
| } | |
| // ... lines 77 - 138 |
Let's put one more down here - yield MenuItem::section()... but this time leave the label blank. So unlike sub-menus, which wrap menu items, you can just pop a section anywhere that you want a separator.
| // ... lines 1 - 57 | |
| public function configureMenuItems(): iterable | |
| { | |
| // ... lines 60 - 72 | |
| yield MenuItem::linkToCrud('Users', 'fas fa-users', User::class); | |
| yield MenuItem::section(); | |
| yield MenuItem::linkToUrl('Homepage', 'fas fa-home', $this->generateUrl('app_homepage')); | |
| } | |
| // ... lines 77 - 138 |
Let's go check it out. Refresh and... very nice! Separator one says "Content"... and separator two gives us a little gap without any text.
External Links
We saw earlier that you can add menu links to point to a dashboard, other CRUD sections... or just any URL you want, like the Homepage. So, not surprisingly, you can also link to external sites. For instance, let's say that I love StackOverflow so much, that I want to link to it. We can tweak the icons, and for the URL, pass whatever you want, like https://stackoverflow.com.
| // ... lines 1 - 57 | |
| public function configureMenuItems(): iterable | |
| { | |
| // ... lines 60 - 75 | |
| yield MenuItem::linkToUrl('StackOverflow', 'fab fa-stack-overflow', 'https://stackoverflow.com'); | |
| } | |
| // ... lines 78 - 139 |
Oh, but let me fix my icon name. Great! Now when we refresh... no surprise, that works fine.
More Menu Item Options
If you look closer at these menu items, you'll see that they have a lot of options on them! We know we have things like setPermission() and setController(), but we also have methods like setLinkTarget(), setLinkRel(), setCssClass(), or setQueryParameter(). For this case, let's ->setLinkTarget('_blank')... so that now if I click "StackOverflow", it pops up in a new tab.
| // ... lines 1 - 57 | |
| public function configureMenuItems(): iterable | |
| { | |
| // ... lines 60 - 75 | |
| yield MenuItem::linkToUrl('StackOverflow', 'fab fa-stack-overflow', 'https://stackoverflow.com') | |
| ->setLinkTarget('_blank'); | |
| } | |
| // ... lines 79 - 140 |
Next: what if we need to disable an action on an entity-by-entity basis? Like, we want only want to allow questions to be deleted if they are not approved. Let's dive into that.
9 Comments
Hi guys, sorry for posting in a random thread, but it's just where I am at the moment, and I'm not aware of a better place for such a report🙂
Since the site overhaul, there's a bug regarding "autoplay" feature – the autoplay switch's state is not persisted between pages. The browser console shows this:
Uncaught TypeError: Cannot read properties of null (reading 'autoplay').Feel free to ask for more details and/or debugging.
Hey @Andrey!
We're checking into this. What browser are you using? And is there any extra stack info on that error? I'm sure there's a problem, but we haven't been able to repeat it yet.
Thanks!
I'm using Arc browser, which is based on Chromium. I also tested on Google Chrome and had the same problem there.
There's no (related) errors in the console, not even the one I mentioned above. You guys probably already fixed that.
I found the video player stores some settings in the local storage, including
autoplayNext. I played around while keeping an eye on it, and can report a few scenarios when the problem happens. It is also kinda weird, and sometime nothing happens, but still a high chance for the problem to happen. Other scenarios I had only once and could not repeat. In all the cases, the "Autoplay" switch correctly updates the setting in the local storage, no problem there.falseand I do not interact with the player (i.e. it receives no clicks).truewhen the video is playing and I click on either seek bar or "+10s" button. Very high chance (about 90%).trueby itself when video is playing and reaches an arbitrary point in time, or sometimes just the endscreen (when "Play next episode" button appears). Somewhat high chance (about 70%).truewhen the video is playing and I click on "Next Chapter" below the player. Happened only once, cannot reproduce.truewhen the video is ended and I click on "Next Chapter" in the center of the end screen. Happened only once, cannot reproduce.I hope it helps somehow!
EDIT: I forgot to mention, when
autoplayNextchanges by itself – only the value in local storage is updated, but not the switch. The switch does not reflect the state in local storage when this happens, that why it looks like the setting is not persisted. Now we know it is correctly preserved after all. The real problem is – it changes spontaneously.Unrelated question – would it be possible, if clicking on "new reply" in your notifications had taken you directly to the comments thread? Right now it just opens the page, not even the "Comments" tab. Sorry if I'm being needy😅
Hey @Andrey!
Thanks for the extra info - SUPER helpful. Someone on our team thinks they might know what's up :).
Not needy! I'd say that's a bug that we hadn't noticed yet! We'll handle it - I appreciate you pointing that out.
Thanks!
Hey Andrey,
Thank you for reporting it, we will take a look soon!
Cheers!
hello, when the site loads, the menu appears expanded, how can I change the code so that it loads collapsed by default?
Hey @gverdu!
You should be able to do that by:
A) In your "dashboard" controller, override the
configureDashboard()method.B) Then, call
renderSidebarMinimized()before returning the object:Source for the docs for that method are here https://symfony.com/bundles/EasyAdminBundle/current/dashboards.html#dashboard-configuration
I hope that helps! I also think the collapsed sidebar looks nice. Oh, and remember: once you have clicked the minimize/maximize, that is stored in the browser's local storage and will override this "default" setting of collapsed.
Cheers!
I don't see the submenu links unless I ditch ->setController(QuestionCrudController::class)->setPermission('ROLE_MODERATOR') respectively ->setPermission('ROLE_MODERATOR')->setController(QuestionPendingApprovalCrudController::class) portion of the code. Of course that makes those sublinks unfunctional. I tried the code downloaded from symfonicasts site with the same result.
My code is here https://github.com/petre-sy...
Hey Diaconescu,
Most probably your logged in user does not have that ROLE_MODERATOR somehow. Please, try to log out and log in again, then check the Symfony web debug toolbar, in particular, the Security tab there - it will show you roles that your user has. It should be in "Roles" or in "Inherited Roles" row. If the user does not have that ROLE_MODERATOR role somehow - please, add it first and try again (you may need to log our and log in just in case).
I hope this helps!
Cheers!
"Houston: no signs of life"
Start the conversation!