-
Notifications
You must be signed in to change notification settings - Fork 191
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
Improving the way the current item is determined #2
Comments
An idea I have is to have a matcher responsible to determine whether an item is current or not. This would allow replacing the implementation with a more complex one. The question here is: should the matcher be injected into the item (allowing to keep the Comments are welcome |
I think each solution has some pros and cons. I think it's more consistent if the matcher is injected into the item, since it changes the item state (current state). But, injecting the matcher into the renderer is more performance friendly. We could suppose that the menu is rendered in each page anyway, so injecting the matcher into the item is not really a problem. I think i'd go for injecting the matcher into the item. Now, i don't know why, but injecting a matcher into an item seems a bit weird to me. Does another object on the top of the items should not be responsible of that ? |
yeah, injecting the matcher seems weird to me (which is why I'm trying to improve the idea to get rid of this need). Regarding your concern about the state, one point is here: should we keep the determination of the current item as a state of the item or move it out of the item (to the matcher). |
I think we need the "current" flag into the item, but if a matcher is added somewhere in the process, the item should definitly not be responsible of using it nor setting its own current state. IMHO, the matcher should not keep any instance of the current items. It should just find the current items in the tree and set the current state onto them. But injecting the matcher into the renderer seems weird too, and having the matching process executed when the menu is built doesn't seem right either since it would add an useless overload. Don't know where is the good solution there :/ |
I wonder if the current state would be ever useful for anything else than the rendering. If not so, using the matcher during the rendering process seems relevant after all. |
I'd strongly prefer having it in the item since being able to check which items are active (isCurrent) can be very handy. Unfortunatly the project is private but I have a project with sf2 and the KnpMenuBundle where I actually use isCurrent to set showChildren and use that to handle displaying a submenu in a different menu. Just a small example, but the current structure (which remains in tact if you place the matcher within the item) gives a developer such freedom, while moving it to the renderer wouldn't. Apart from that I think that creating a seperated matcher would be very nice and would be a better solution then my PR on the KnpMenuBundle which simply puts a regexp in the item. |
well, the matcher would not be a private object inside the renderer. You could still use |
Btw, what do you think about the other issue pointed in the original post: multiple current item. Should we allow only one current item in the whole tree (thus making it meaningful to retrieve the current item) or should we keep allowing multiple current items (and thus deleting the method to get the current one as it is lying by giving only the first found) ? This decision will impact the way the matcher is implemented |
@stof: I think the multiple current item is a common case, especially for submenus (when an item from a submenu is current, i want all its parents to be current too). |
the parents of a current item as considered a currentAncestor currently, and receive the |
you should allow multiple current items, again to avoid disallowing that option. |
Then we have to remove the Note that getting all the current item can be done by using the power of PHP iterators. |
i would also like to see a solution here. i have a action which shows a paginator, and if i go to next page my menu is missing the paginator is also stuck (Knp Paginator Bundle) showing the correct page... any ideas ? cheers phil PS: i love you bundles anyways! |
sorry got to revorke...
and for zend paginator used in knppaginatorbundle
|
Right now I have just added such a code to the menu builder switch($this->container->get('request')->attributes->get('_route')) { case "videoView": case "videoList": $menu['mainmenuVideo']->setCurrent(true); break; case "mediaView": case "mediaList": $menu['mainmenuMedia']->setCurrent(true); break; case "newsView": case "newsList": $menu['mainmenuNews']->setCurrent(true); break; } Its simple and can implement any extensive logic. But I think, that the best solution - add a couple options for determining current page. So developer will have choice - how to detect current page. $menu->addChild('mainmenuVideo',array('route'=>'videoIndex'),'attachedRoutes'=>array('videoView','videoRelated','videoTagsSearch')); So whenever some of the routes listed in attachedRoutes used, menu item will be selected. Option #2. Sometimes more complex logic may be required. For example, I have News entity in my site. News can belong to 1 of 3 groups - Public Release, Review, Article. |
@zhil, can I just make a note that your switch solution does not work when using ESI because the value of |
yeah, for ESI request, you probably need to propagate the main attribute through a GET attribute and use it instead. |
thanks for the note and possible solution. already do the same :) |
It seems like this discussion is a bit in "sleep" mode? Did you came to any conclusion? This issue is very common and it will be really nice to see it solved. |
I have solved customisation of current item in this way: kmpmenu i have it as a service, i need router in builder so i need to send it into service as argument arguments: ["@request", "@router"] in MenuBuilder i will need to add: use Symfony\Component\Routing\Router; change: public function createMainMenu(Request $request, Router $router )
{
$menu = $this->factory->createItem('root');
$menu->setCurrentUri($router->generate($request->get('_route'))); so now will be current item set correctly even when in url will be some junk ... and when i want to set some other item as current i can do it in controller very simply: $menu = $this->get(mybundle.menu.main');
$menu->setCurrentUri($this->generateUrl('my_route')); maybe this can help someone... |
any official plans for that? it is really a common requirement. having a simple crud for, let me say articles, with a single main menu. this feature is really important. |
@c33s This issue is still in my mind. But I haven't had a flash showing me how to solve it in a good way. The idea I have in mind is not a working solution currently. And I unfortunately don't have enough time to work on all stuff I would want to and other stuff jumped higher in my todo-list |
what about a temp solution? i don't have to be perfect, also if it may not be the final solution, it is a better solution, than have this feature missing. what about the solutions already posted:
@stof what do you think? |
@c33s the activeMask solution requires changing the ItemInterface. Modifying the interface for a temp solution is not acceptable (as interfaces should stay BC except for good reasons) and the solution in the comment above is something done in the builder code, i.e. in userland so you can use it |
I think that i'm far from being an expert but what about creating a matcher service, as suggested by @stof, the current route would be injected inside it as would be the menu. If you don't want the MenuItemInterface to be modified, what about configuring the matcher service with a specific config file ? The idea is to associate a menu entry with multiple route name. Sorry for my poor english! |
@baikunz My issue is about the way the matcher service should be used. I see several solutions
|
Oh ok I think i missed that point ! by the way IMHO and for what it worth I was thinking of something like the first solution, I remember I had to use something like that while dealing with Android and the user was responsible to call explicitly the matcher to match the Uri. |
i think it is importent, that not every route have to be defined. often you only have a single level menu visible like: home | events | news | .... from the routing side its there are a lot of "subroutes"
so i can continue this list, i am sure you get the point. i sould really be easy to simply define each event route should mark the 1st level event element as ancestor. maybe it is easy to define a routename wildcut matcher (would be better than a url matcher). using such a menu system should help the developer to reach his goal fast and easy. not having to create tons of services, enter every route which is in his project,... RAD is a thing which is really important. i allways loved the input from @fzaninotto to @symfony, because he was the link between high end, high quality code and fast and easy usability for the end-developer. |
@c33s yeah you are right having to specify each routes seems too much work. A routename matcher could be a great alternative but it then become dependant of the routenames so what about routenames defined in third party bundles? |
@baikunz My idea is to have an item matcher, i.e. allowing to match on anything you want available in the item (and it is one of the reason I added the support for extras in the item a few weeks ago) |
@stof doesn't it mean that in some way the item itself is aware of how it have to be treated? |
@baikunz no, what it means is that the matcher receives the whole item. The extra array is simply a container for additional stuff. the item does not know anything about what they are. It only stores them. |
@stof Ok I got it, it seems quite good, but I still don't get how you could easily make the link between an item and a route/url with that solution. I see 2 ways of doing it
|
@baikunz |
@baikunz if your matcher expects this, it is possible too |
Ok, I'll try something when I have some time |
Well, I have a full week now before the start of my internship. So I plan working on it (and on some other bundles) |
Ok then i'll be glad to bring you some help if you need. |
Please look at #49 |
Currently, the library still uses the behavior coming from KnpMenuBundle:
There is some improvements needed here:
getCurrentItem
method is lying by giving only the first found (should it be removed entirely ?)The text was updated successfully, but these errors were encountered: