Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update sidebar.blade.php #3121

Closed
wants to merge 1 commit into from
Closed

Update sidebar.blade.php #3121

wants to merge 1 commit into from

Conversation

joelmellon
Copy link
Contributor

The current sidebar menu implementation isn't very smart when it comes to detecting which menu item should be "active" - it merely looks for the beginning of the URL in the href (and vice versa) which leads to multiple menu items being highlighted at once when they both begin with the same word, eg. user and usersetting. See screenshot for my use case:

Screen Shot 2020-08-15 at 10 58 52 AM

Above, I've got CRUD for models called `trail` and `trailhead` which means that when I'm on the trailhead page, both the Trailheads menu item is active (correctly) and the Trails menu item is active (incorrectly).

This pull request implements improved logic to determine if menu item is active.

It could be made in better by also comparing the URL parameters (URL segment after the ?) but I think this is a significant improvement already.

Use smarter logic to determine if menu item is active
@welcome
Copy link

welcome bot commented Aug 15, 2020

BOOM! Your first PR with us, thank you so much! Someone will take a look at it shortly.

Please keep in mind that:

  • if this constitutes a breaking change, it might take quite a while for this to get merged; we try to emulate the Laravel release cycle as much as possible, so developers can upgrade both software once; this means a new big release every ~6 months;
  • even if it's a non-breaking change, it might take a few days/weeks for the PR to get merged; unless it's a no-brainer, we like to have some community feedback on new features, before we merge them; this leads to higher-quality code, in the end; we learnt this the hard way :-)
  • not all PRs get merged; sometimes we just have to hold out new features, to keep the packages lean; sometimes we don't include features that only apply to niche use cases;
  • we're not perfect; if you think we're wrong, call us out on it; but in a kind way :-) we all make mistakes, best we learn from them and build better software together;

Thank you!

--
Justin Case
The Backpack Robot

@@ -58,11 +58,11 @@ function() { return $(this).attr('href') === full_url; }
// If not found, look for the link that starts with the url
if(!$curentPageLink.length > 0){
$curentPageLink = $navLinks.filter( function() {
if ($(this).attr('href').startsWith(full_url)) {
if ($(this).attr('href').split('?')[0] === full_url) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JavaScript's split always returns an array with at least one value, so even if there's no ? this still works as expected.

return true;
}

if (full_url.startsWith($(this).attr('href'))) {
if (full_url.split('?')[0] === $(this).attr('href')) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above.

@scrutinizer-notifier
Copy link

The inspection completed: 5 updated code elements

@tabacitu
Copy link
Member

Thanks a lot of for the PR @joelmellon ! I agree that this bit of logic could use some work. It has corner cases like yours that are just not covered well.

I agree with you that splitting by ? will work well for the Create operation. But my tests show a big problem: this renders the menu item inactive for all other operations. That's because the sidebar only points to the List operation, not the other ones. That's the entire reason why we chose to go with startsWith(), so that all operations for a CRUD make the menu item active.

Screenshot 2020-08-17 at 07 24 10

The current implementation does leave out the use case you mentioned, though, and I hate that.

Good news though - I have an out-of-the-box fix for it 🤣 Something that I've been eyeing for a while now but never got to do because new versions have been feature-packed already: we should probably make the route segment plural, not singular (maybe see Laravel-Backpack/Generators#63 for details). We only made it singular to match the Laravel convention at the time, even though we didn't agree to it. Now Laravel has made restful controllers plural, but we haven't, just to keep backwards-compatibility.

But making the route segment plural, we should, in theory, fix this too, because the routes would be:

  • admin/trails
  • admin/trailheads

So for most corner cases like you mentioned, it should fix the problem. Right?!

What are your thoughts on this @joelmellon ? Do you have a different programming solution to fix the problem above (sidebar items not active on other operations than List)? If not, I guess a quick fix for your project would be to implement plural route segments already. It's easy, just change the segment name both in routes/backpack/custom.php and inside the Controller itself, under setRoute().

Let me know what you think.
Cheers!

@tabacitu tabacitu added the Possible Bug A bug that was reported but not confirmed yet. label Aug 17, 2020
@joelmellon
Copy link
Contributor Author

joelmellon commented Aug 17, 2020

@tabacitu "this renders the menu item inactive for all other operations" - I didn't even think about this (or notice it.) 🤦🏻‍♂️

I personally really like the plural URL segment convention, especially for index pages, but I prefer when they're singular for view, and edit, and create. I don't have a strong opinion though, and if Laravel's going in one of these directions, all the more reason to adopt it. Consistency is more important to me.

I don't think it completely solves the problem, which you've pointed out, but it's a great leap in the short term. The issue I foresee if this logic doesn't change, is in the example I gave for users/usersettings. If the admin/user route is changed to admin/users and there's an admin/usersettings route, both would be active in the nav since both start with admin/users.

Again though, I do see your proposed solution as an improvement, and I'll be implementing it instead of the fix in the PR here for my own project.

I don't have a ton of time to come up with something better, but if I do I'll let you know. Off the top of my head, I think there nav libraries out there that do this type of thing well, but I couldn't name any. In any case, the first step would be to nail the the definition (aka business rule) for what active means related to the URL. To me it's closely related to what comes before the GET vars, but if a user had GET vars in their nav link, they might expect the menu item to only be active if the exact URL matched, so it may not work for everyone. ‾\(ツ)/‾

@tabacitu
Copy link
Member

Hmm you're right. There would still be uncovered cases, even with plural. So it still needs better a better JS solution.
@pxpm what's your take on this?

@martijnb92
Copy link
Contributor

I made a small PR #3136 to enable the active class for menu items in the header. Also works for example the "My account" page in the dropdown user menu.

@tabacitu
Copy link
Member

The issue I foresee if this logic doesn't change, is in the example I gave for users/usersettings. If the admin/user route is changed to admin/users and there's an admin/usersettings route, both would be active in the nav since both start with admin/users.

Damn it. You're right @joelmellon there's still that use case that wouldn't be covered...

@tabacitu
Copy link
Member

@joelmellon looks like we can't really consider this bug fixed. But we can't merge this either. Tough one. I'm going to close the PR though since we can't merge it.

In the future, we'll:

  • move towards plural in the route name (should at least reduce the number of issues)
  • figure out a different solution for that use case where the plural + second word end up being the same string, for ex:
    • /admin/users + /admin/userprofiles will be fine;
    • /admin/users + /admin/usersetttings will NOT be fine, they both have users;

But now that I think of it, if the end solution is a better convention (plural) I'm pretty sure another convention will fix the use case above too - using dashes. Right?! Freakin' dashes 🤣 Hear me out - if we use plural for route URLs AND use dashes to split words inside the route URLs we'll end up with:

  • /admin/users + /admin/user-profiles which will work fine;
  • /admin/users + /admin/user-setttings which will again work fine;

Quite a simple solution, right?! 🤣 Why didn't we think of this before?!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Possible Bug A bug that was reported but not confirmed yet.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants