Closed (duplicate)
Project:
Drupal core
Version:
8.3.x-dev
Component:
menu_link_content.module
Priority:
Normal
Category:
Feature request
Assigned:
Unassigned
Issue tags:
Reporter:
Created:
23 Apr 2012 at 18:50 UTC
Updated:
21 Dec 2016 at 15:14 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #1
amontero+1.
Searching for how to allow empty paths reveals that this is a popular requested feature, especially to accomplish multi level menu parent items that should lead to nowhere, just contain more items.
I tried modifying drupal_valid_path to accept "#" as a valid path, but didn't worked. Menu item is not displayed in the menu item list admin page (however, it is saved in the DB). I can't figure it out with my current core knowledge. Anyway, the # path may not be the best solution.
Also tagging to make it more visible (added "DrupalWTF" tag because seems such an obvious feature to me).
It's a must have to allow multilevel menus, and ML menus are needed in lots of scenarios, IMO.
Related modules:
https://drupal.org/project/special_menu_items
https://drupal.org/project/void_menu
Comment #2
shp commentedIn my opinion "
<none>" is better than "#".P. S. The extension of the patch must be ".patch" and the status of the issue must be "needs review" to be patch automatically tested.
Comment #3
amonteroSearching around later I found also
<none>as a possible path, and I like it more, too.I attached the patch in txt form to avoid the testbot go through it, since I actually know it is failing and it was just a "trying luck" quick attempt :)
Comment #4
amonteroDefinitely seems that going the
<none>way would be safer. Using # may conflict with several issues:#123103: Retain #anchors during path alias -> normal path saving
#325533: Allow <current>#fragment as a menu path
#759808: Disallow # character in path aliases
Comment #5
mgiffordCurios why this is tagged with accessibility? The accessibility issue hasn't been defined.
Comment #6
gagarine commentedI'm the maintainer of special menu items. I think it would be better to create a more extensible system using token. The basic idea is module can register a function than return the link content for token like , , ...
See #1287610: Create a Menu Item Type API
Comment #7
webchickLooks like there is a patch here, although it's needs work. Marking appropriately. We would also need tests for this.
Comment #8
mgiffordbumping the bot as this should be tested. It applies nicely in .git, but not sure if it needs the .patch extension.
Comment #9
mgiffordbasically it's #1.
Comment #11
mgifford#9: allow-empty-menu-path-9.patch queued for re-testing.
Comment #13
idflood commentedWith the following patch the menu get displayed but it behave like the
<front>. I tried to modify the theme_menu_link function but it doesn't have any effect, certainly a little piece I'm missing.Comment #14
shp commented+1 for "
<none>" instead of "#"!Comment #15
jordanmagnuson commentedAlso agree that the path should be "", rather than "#"
Comment #16
idflood commentedWith the following patch if a menu item as a path
<none>it will not be outputted as a link but simply as text. I believe some work is still needed but it should be a good starting point.edit: Here are some things missing:
<none>special path just like the<front><none>path we should automatically expend itI certainly forgot some other remaining tasks so if you have other ideas feel free to add them.
Comment #17
aaronmchaleHi, just saw this from another module.
This would be a great solution to this problem. I havn't tried out this patch yet, however I was wondering if it still creates an <a></a> tag, because when applying styles if there is no <a> tag in e.g. a main menu, when it comes to creating interactive menus, not having the <a> tag can conflict with some menu styling techniques.
Comment #18
idflood commented@AaronMcH: The patch in #16 simply remove the < a > tag if a the link is < none >.
Here is a new patch which adds a < span > around the element title. This should resolve the possible styling issue I hope. The only possibility that I see with the < a > tag would be to make an href="#", but that would break javascripts relying on the url to define a state for instance.
Comment #19
idflood commentedComment #20
aaronmchaleThe problem that I am having is that "#" isn't recognised as a path when trying to create a new menu item. I wonder if you could make it configurable under the settings for that menu, as I could think of a number of possible HTML tags that a person might want to use.
That actually give me another idea, what if "<none>" just removed the "<a>" tag from the output, However the user could use say "<tag>p class="note"" or "<tag>a href="#"", where anything after the "<tag>" would be wrapped around "<>"e; in the output, and at the end the closing tag would be inserted.
What do you think?
Thanks
Comment #21
mgifford#19: allow_empty_menu_path-1543750-18.patch queued for re-testing.
Comment #22
mgifford#19: allow_empty_menu_path-1543750-18.patch queued for re-testing.
Comment #24
dagmarRe-rolled
Comment #26
crutch commentedneeded to fire menu minipanels if wanting to use click trigger instead of hover
Comment #27
andypostRelated issue #916388: Convert menu links into entities
Comment #28
mgifford#24: allow_empty_menu_path-1543750-24.patch queued for re-testing.
Comment #30
mgiffordJust a re-roll, but I'm getting an error with
PHP Fatal error: Cannot redeclare menu_link_load()that might be related to another patch. Not sure.Comment #31
mgifford#30: allow_empty_menu_path-1543750-30.patch queued for re-testing.
Comment #33
andypostI see no code around that redeclares menu_item_load()
Comment #34
tstoecklerThe comment should be updated.
Comment #35
progga commentedRerolling patch #30 with the help from folks at the Drupal Drop In Sprint - London February 2013
Comment #36
andypost#34 not addressed
wrong code indent
this comment should be changed as #34 suggests too
Comment #37
progga commentedRerolled patch #35 based on @andypost's feedback.
Comment #38
andypostGreat! Now it needs test coverage for RTBC
Comment #39
smira commented+1 for RTBC
i tested on latest d8 build and works like a charm
Comment #40
smira commentedComment #41
pjcdawkins commentedSee #38 - it needs automated tests.
Comment #42
idflood commentedI tried to add some tests but I'm not sure if I made anything right. It works but the test may belong to another file, and the tests are probably too specific.
Comment #44
idflood commented#42: allow_empty_menu_path-1543750-42.patch queued for re-testing.
Comment #45
mgiffordthat works for path
<none>when I added a new menu item to the footer - admin/structure/menu/manage/footerI think someone should look over the tests and mark it RTBC.
Comment #46
progga commentedCombined the 2 patches from #42.
Comment #47
dawehnerThe drupal code style is a bit odd here: it should be "elseif"
Maybe it's easier to read when it's using an in_array($path, array('
Should be \Contains ...
Have you tried making this a DrupalUnitTest? I don't see any browsing on the actual site, so this seems possible, even if it's harder to do.
According to http://drupal.org/node/1354 there should be an empty lines after the class.
it's odd to have a parameter. I don't think that something calls the test method with a parameter :) .. Additional this method should be marked as public.
Comment #48
aspilicious commentedIt doesn't happen a lot but I had a usecase where I had to create a "#something" path (yes, an internal page link) on a menu item. But drupal doesn't allow that.
Probably another issue but I would see this solved too.
Comment #49
progga commentedUpdated patch #46 based on @dawehner's 1st and 3rd suggestions.
@aspilicious, this patch will not allow you to enter "#something" as a menu path. Sorry to disappoint you :-(
Comment #50
klonosI'd be interested in that too. Separate issue then?
Comment #51
amontero@aspillicious @klonos: comment #4 has links to issues that may be related.
Comment #52
dawehnerIs there a reason why we can't use DrupalUnitTestBase here?
Comment #53
progga commented> Is there a reason why we can't use DrupalUnitTestBase here?
Because url(), drupal_valid_path(), etc. hits the database. The relevant tables will be absent during unit test runs.
Comment #54
mparker17@mgifford asked in #5 why this was tagged with accessibility, but I don't think that question ever got answered. Anybody know?
Comment #55
kbell commentedDoes anyone know the backport-to-D7 status of this patch?
Thanks,
Kelly
Comment #56
mgifford@mparker17 - I suspect it's because people would like to add skip-links to the navigation. Having a menu that allows you to jump to specific anchors would be quite useful.
@kbell - Until it's committed to 8, the backport to 7 likely isn't going to be started.
Comment #57
andypost+1 to anchors
Comment #58
mgifford#49: allow_empty_menu_path-1543750-49.patch queued for re-testing.
Comment #60
mgiffordfunctions moved to core/modules/menu_link/lib/Drupal/menu_link/Plugin/Core/Entity/MenuLink.php
core/includes/common.inc seems to no longer be relevant.
Comment #62
andypostThere's no $entity use $this->external
Comment #63
mgiffordThis makes sense looking at the code. Thanks @andypost!
Comment #64
amateescu commentedThe patch looks good to me, but we still need test coverage..
Comment #65
dawehneradd tag
Comment #66
idflood commentedHere is a simple reroll of the test I created in #42. The second file contains the test and the patch from #63.
I'm not sure why the url function is not modified in #63 like it was in #42 but there may be a good reason for it. So we either can remove the test on the url function or fix it, both solutions should work.
Comment #67
amateescu commentedThis test should be moved to the menu_link module.
Contains \Drupal...
This should be a DrupalUnit test.
Missing {@inheritdoc}.
That doesn't sound right :)
This is weird, why do we escape the first one but not the second? Same for all occurences in this test.
Maybe "Menu items without a path are displayed as a element."?
Comment #68
idflood commentedThanks for the review. Here is a reroll with some corrections but not all.
Checked on other tests and this line looks right. Could you explain what is wrong?
#53 explain why this can't be a DrupalUnit test.
This is not present on all other tests I checked but I still added it : )
edit: I wanted to make the url method pass the test again but I've found that it changed a lot... We certainly need to make something like PathProcessorFront.
Comment #70
amateescu commentedNot all files have been upgraded to the new standard, which is "Contains \ClassName". See https://drupal.org/node/1354#file.
This is exactly why I said DrupalUnit test and not just Unit test :) More specifically, I'm talking about DrupalUnitTestBase, which has the ability to create database tables.
About {@inheritdoc}, yes, I know not all files have them, but that shouldn't stop us to make the new ones right ;)
And now for some more nitpicks:
Missing empty line before the docblock of this method.
Tests creation..
All methods should specify their visibility, in this case it's 'public'.
My mistake in the previous post, the
<span>tag was cut off. So this should be: 'Menu items without a path are displayed as a<span>element.'Same problem as before, the right > is not escaped.
And now you made me curious about url().. what exactly doesn't work about it?
Comment #71
idflood commentedThanks for the review and the explanations : )
The url() function return something like this if you pass < none >: drupalroot/%3Cnone%3E
The test check for an empty string which should be better I think.
Comment #72
idflood commentedOops, I forgot to remove a thing I added to check what returned the url method.
Comment #74
kovacevo commented#63: allow_empty_menu_path-1543750-63.patch queued for re-testing.
Comment #75
amonteroReroll.
Comment #77
amonteroReroll keeps failing on the same single test: "Url return an empty string." on EmptyLinkPathTest.php, line 40 - Drupal\menu_link\Tests\EmptyLinkPathTest->testEmptyLinkPath()
First attempt to fix the failing url() return value test. Instead of expecting url() returning '', now it expects '#'.
Also, the url() function still needed to be modified for dealing with ''. Now it should do with adding a path processor for it (PathProcessorNone.php).
Comment #79
amonteroErroneous git format-patch against wrong branch. This is the right patch for #77.
Comment #81
mgifford#79: drupal--1543750--allow-menu-items-without-path--79.patch queued for re-testing.
Comment #82
mgiffordThere was just this one error in the test last time:
Url return a '#' string. Other EmptyLinkPathTest.php 40 Drupal\menu_link\Tests\EmptyLinkPathTest->testEmptyLinkPath()
Comment #84
mgiffordReroll
Comment #86
mgifford#84: drupal--1543750--allow-menu-items-without-path--84.patch queued for re-testing.
Comment #87.0
(not verified) commentedSome illustrations...
Comment #88
mgiffordreroll
Comment #89
mgiffordComment #92
mgiffordHmm, this is failing to install with this on simplyTest.me:
Seems ok though in my local install.
Comment #93
internetdevels commentedAdded new patch.
Comment #95
mgiffordreroll...
Comment #97
mgiffordOk, not sure what changed here, but...
WD php: ReflectionException: Class [error]
Drupal\Core\PathProcessor\PathProcessorNone does not exist in
ReflectionClass->__construct() (line 959 of
/var/lib/drupaltestbot/sites/default/files/checkout/core/vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/ContainerBuilder.php).
ReflectionException: Class Drupal\Core\PathProcessor\PathProcessorNone does not exist in ReflectionClass->__construct() (line 959 of /var/lib/drupaltestbot/sites/default/files/checkout/core/vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/ContainerBuilder.php).
Drush command terminated abnormally due to an unrecoverable error. [error]
Comment #98
slotid commentedIn a file js.js which is marked in the *.info file in your theme directory put a code like that one below
Comment #99
mgiffordSo, this change (adding %none):
core/modules/menu_link/lib/Drupal/menu_link/MenuLinkFormController.php
needs to get moved to:
core/modules/menu_link_content/src/Form/MenuLinkContentForm.php
core/includes/menu.inc core/includes/path.inc & core/core.services.yml are all changed too.
Comment #100
paulmckibbenThis needs pretty significant re-architecture since the last patch. I started to try, but quickly got lost. :)
A key change is that the Link field is now used to implement the menu link destination field. I don't think it's a good idea for the Link field to support <none> by default.
Also, https://www.drupal.org/node/2421941 has a discussion about removing the use of <front>.
Where does all this leave this issue? For example, would it make sense to NOT require a value in the link destination field, allowing it to be empty?
Comment #101
aaronmchaleI think these should still exist, the difference between these and is front represents an actual path, which really should be just a /, whereas these are like technical replacement tokens that perform special operations.
Comment #102
rishikant05 commentedComment #103
rishikant05 commentedComment #104
mikey_p commentedSo I just dug into this a little bit and i think there are going to be three main components to supporting this (either in core or contrib):
1) Menu link content entity needs to have altered definition to make link field not required. This pretty much works just by altering the baseFieldDefinitions().
2) Menu link plugin type needs to support having an empty link or empty URL related parameters.
3) The menu.html.twig template will need to check the menu_link isn't empty before printing the link, and alternately just print the title.
I tried this and the main problem I ran into is that of course portions of the MenuContentLink entity assume a link is required. The entity technically saved to the DB just fine, but the postSave() method calls some bits to update the menu link plugin definition, which tries to load the URL from the link, which is NULL and produces a fatal error. If this is supported in contrib, then this will probably need a new entity class to extend/override core/modules/menu_link_content/src/Entity/MenuLinkContent.php.
Comment #105
mlevasseur commentedRerolled...
Conflicts: core/core.services.yml, core/includes/menu.inc
Removed: core/includes/path.inc, core/modules/menu_link/lib/Drupal/menu_link/MenuLinkFormController.php
Comment #107
mikey_p commentedI don't think the patch above is moving the right direction. Instead of allowing a new path, we should be working towards not requiring a path at all. Further, theme_menu_link() shouldn't be added as that is not part of menu.html.twig. Likewise, the changes to template_preprocess_links() don't make any sense either as you can see it has support for handling text links (items without a URL) and the changes there will break links.html.twig anyway.
Comment #108
danielbeeke commentedI created a proof of concept to fix this with a contrib module
https://www.drupal.org/sandbox/danielbeeke/2515610
Comment #109
Internet commentedD8 - As above tried above in #1.
We used 'url path setting': /# (# on its own would not be accepted) and the placeholder appears to work fine with bootstrap light.
Result: a class="dropdown-toggle" aria-expanded="false" aria-haspopup="true" role="button" data-toggle="dropdown" href="#"
Comment #110
dawehnerThis sounds like a perfect feature request for 8.1. Its also great that we indeed already have a contrib module, thank you @danielbeeke
Comment #111
danielbeeke commentedI have updated menu_link_placeholder.
The module makes it possible to skip the field 'path' like mikey_p said.
To use the module you need to change your menu.tpl. As mikey_p said, the rendering of a link is where it goes wrong.
In preprocess_menu_link the module adds 'no_link' => TRUE, my template picks that up and renders a span.
Maybe we can do something like that too in core?
Comment #112
dawehnerWell, let's discuss how to implement it properly, that for sure is a good idea.
Comment #114
manuel garcia commentedSo now that #2693725: Add <nolink> to allow for non-link links is in, do we still need this?
Comment #115
mgiffordI can't see why. We can re-open if needed.
Comment #116
generalredneckLooks like the functionality that was commited to 8.2.x doesn't allow you to do this via the UI so I don't know if this matches yalls usecase or not... I'm using the latest 8.2.x-dev as of today.
http://screencast.com/t/QYk74K0xspk
http://screencast.com/t/TsblTBTuHT
Comment #117
pixelsweatshop commented@generalredneck, I see you used<none>when it looks like it should be<nolink>Edit: Removed. Your second image wasn't working when I looked at it. I see you tried nolink as well.
Comment #118
andrej galuf commentedGUI fails because the form validates the path and <nolink> is not a valid path (unlike <front>, which gets converted into one). This originates in MenuLinkContent.php's baseFieldDefinitions, which defines the link field as... well... link.
Comment #119
ckaotikReopened as the GUI does not yet allow for this yet.
I've worked around this using this patch, however I don't feel that it's the best solution to work with this. Patching \Drupal\Core\Url certainly doesn't feel right, there must be a better solution :/
Comment #121
stephen ollmanHow to get this progresses into the next Core release?
It's nice functionality to have and the requirement has been around since the early days of Drupal, so I'm surprised that it still hasn't been included in D8.
Comment #122
rcodina@Stephen Ollman I'm surprised too. I was expecting this to be included on 8.2 version! In drupal 8 we have no Special Menu Items module! Anyone knows a workaround?
Comment #123
danielbeeke commentedhttps://www.drupal.org/project/special_menu_items
It is there.
Comment #124
andrej galuf commentedI've thrown myself at this this morning, starting with previous solutions above. Three things would need to be fixed in order to get this working (GUI inclusive):
Note that the comment for Url::fromInternalUri is false - the method does not accept <front> and <none>, it throws InvalidArgumentException if they are passed. However, <front> is converted to an internal path before that happens and <none> is not (we'll get to that). Ironically, the same method creates <front> and <none> afterwards, which are then validated and converted into urls. So we pass <none>, which gets converted into 'internal:', only to get reconverted into <none> again. Go figure.
Based on #2421941: Determine whether not only "/" but also "<front>" should be valid input for the Link widget I say the right solution is to stop the whole conversions with <front> and <none>, link should be allowed to be empty (i.e. not required) and done. This would return an empty href, which the template can render as <span> instead of <a> and we'd be done. Unfortunately, the value null also gets rejected, which means this is a dead-end without further modifications.
As it turns out, the key hides not in Url or in MenuLinkContent, but in LinkWidget, specifically in LinkWidget::getUserEnteredStringAsUri. This method is responsible for converting the string <front> into 'internal:/' (see line 118). If we add another condition right after it that converts <none> into an empty string and keep the validation from 1st point above, the GUI passes, validates and saves the value 'internal:', which returns a link with an empty href. Now it's just a matter of a link template handling empty href as a span. And to finalize it, fix LinkWidget::getUriAsDisplayableString to convert an empty (null) path into <none>
Required adjustments to LinkWidget are attached.
Comment #125
alexfdg commentedI´m not a code expert and I look for easy ways to solve issues without extra modules,
so I found this solution, hope somebody helps: http://www.thecomputergroup.com/blog/how-to-make-a-drupal-menu-item-link...
Comment #126
pwolanin commentedYou can already use a path of
route:<none>orroute:<nolink>so I think we can call this fixed.Comment #127
davidhernandezI believe the intention is to not have it render an tag. Doesn't route: still do that?
Comment #128
dawehnerThe link generator certainly has dedicated code for exactly this usecase:
given that, this seems to be solved already.
Comment #129
jibranThis is a duplicate of #2693725: Add <nolink> to allow for non-link links .
Comment #130
davidhernandezYes, I see. Didn't realize it before, but it indeed now produces a
<span>tag instead of<a>. That's workable.Comment #131
ckaotikYes, the functionality of a
<nolink>route is supported by core, as per #2693725: Add <nolink> to allow for non-link links . But no, the ui does not allow its use yet. A link field (e.g. on a menu link) with input of<nolink>is still rejected inDrupal\link\Plugin\Field\FieldWidget\LinkWidget::validateUriElement().This was exactly my point when I reopened this issue months ago. Andrej (see #124) also nicely described what's happening and came to the same conclusion. Without a patch, non-developers have no way of using this option.
Comment #132
davidhernandezYou have to input
route:<nolink>. Not the most user friendly.Comment #133
aaronmchaleI'm with @davidhernandez, user shouldn't be required to input "route:", but where to proceed, does ths get re-opened, new issue, re-open issue linked in #129, does it even matter that the user needs to provide "route:"?
Comment #134
tim.plunkettNew issue please. The original premise of this (and the other) issue is addressed. It is no possibly, no matter how unwieldy.
Comment #135
giorgoskWhy is this no in the description underneath
"route:< nolink >" so people don't have to look in the forums for something so simple ?
should we put a feature request ?
Comment #136
leon kessler commentedThere's an issue using
route:<nolink>whereby the LinkGenerator considers this a link to the front page. This mean the active class gets set incorrectly.I've opened a separate issue with patch: #2838351: Links with no path get active class on front page