Repository navigation
bug(aria/menu): ngMenuItem value is required but unread, and the documented examples do not compile #33682
Description
Is this a regression?
No.
Description
MenuItem.value is declared input.required(), but inside an ngMenu nothing reads it except a dev-mode duplicate check. The documented examples reflect that — several of them omit value — so they don't compile under strictTemplates.
The documented examples fail to compile. The JSDoc shipped on MenuBar and on MenuItem itself both show items without a value:
<div ngMenu #fileMenu="ngMenu">
<div ngMenuItem>New</div>
<div ngMenuItem>Open</div>
</div>Compiling that with strictTemplates (@angular/aria 22.1.0):
error NG8008: Required input 'value' from directive MenuItem must be specified.
10 <div ngMenuItem>New</div>
~~~
The same shape appears in maintainer guidance — e.g. <div ngMenuItem (click)="markAsRead(item)"> in the discussion on #33303, described there as the designed usage.
Nothing in a menu reads the value. MenuPattern constructs its List with value: signal([]), so neither list selection nor list navigation ever consults an item's value. The two remaining reads are:
MenuPattern.submit(), which passesitem.value()to the panel-levelitemSelectedcallback.MenuPattern.validate(), which warnsDuplicate value '…' detected inside ngMenuunderngDevMode.
So for anyone who handles activation per item (a (click) on the item, as the docs show) rather than through itemSelected, the value is write-only — and it cannot be omitted, because every item would fall back to the same value and any panel with two or more items would report a duplicate-value violation.
The flag looks vestigial. ngMenuItem used to bind [attr.aria-label]="value()", which gave every item a required accessible name and a reason for the value to be mandatory. That binding was reported as a bug (#32893) and removed in #33202, but the required flag stayed.
Proposal
Make value optional on ngMenuItem:
value = input<V | undefined>(undefined)(or default it to the item's generatedid, which already exists and is unique per item).- Skip the duplicate check for items with no value, so a panel of valueless items is valid.
itemSelectedthen emitsundefinedfor such items, which is accurate: the consumer never named one.
Radio and checkbox items still want a meaningful value, and this doesn't change anything for them — it just stops requiring one from plain action items.
Why it can't be worked around in a wrapper
Wrapping MenuItem in hostDirectives doesn't help: Angular rejects a host directive that leaves a required input unexposed —
error NG2019: Required input 'value' from host directive MenuItem must be exposed.
— and hostDirectives only allows an alias, never a value. So a wrapper library has to keep the attribute in its own public API and reach into the input signal's node to fill it, which is what we ended up doing.
Reproduction
No StackBlitz: the reproduction is the five-line snippet above — @angular/aria's own documented example — compiled with strictTemplates: true.
Environment
- Angular: 22.1.0,
@angular/aria: 22.1.0 - Verified with
ngcandstrictTemplates: true.
Filed by Claude, Anthropic's coding agent, on behalf of @artaommahe. The compile errors and source references above were verified locally against @angular/aria 22.1.0.
Activity
crisbeto commentedon Aug 16, 2026
I sent #33686 to fix the doc strings, but we should still discuss if having the
valuebe required is something we want. As far as I can tell, we have it as a side effect of the menu pattern inheriting from the list pattern. cc @ok7saiok7sai commentedon Aug 17, 2026
Practically delegating the item selection event to one single
(itemSelected)is more performant and memory efficient than binding(click)to each menu item. That's why we wanted to encourage such pattern when designing the menu (and list selection behavior).docs(aria/menu): fix doc string examples (#33686)
docs(aria/menu): fix doc string examples (#33686)
artaommahe commentedon Aug 17, 2026
@ok7sai we're building our menu component around aria/menu and having a value/itemSelected pair, especially with nested lists, feels really wrong and as a bad dx. Having one itemSelected forces developers to create one orchestrating function for all menu items that looks just like a big switch/case, instead of binding directly to specific class methods for each action. It works even worse when you want radio/checkbox items that should have their own group-like wrappers and handlers.
angular-automatic-lock-bot commentedon Oct 19, 2026
This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.
Read more about our automatic conversation locking policy.
This action has been performed automatically by a bot.