Not able to return MenuItem[] through a function to model attribute in SplitButton component.
Describe the bug
Hello everyone,
I was trying to pass a function to the [model] attribute in split-button component, but for some reason even when I'm returning a valid MenuItem[] array. the options in the dropdown freezes completely and became unclickable. I added a stackblitz reproducing the issue.
Pull Request Link
No response
Reason for not contributing a PR
- [x] Lack of time
- [x] Unsure how to implement the fix/feature
- [x] Difficulty understanding the codebase
- [x] Other
Other Reason
No response
Reproducer
https://stackblitz.com/edit/efczrox7?file=src%2Fapp%2Fsplit-button-basic-demo.ts
Environment
I-m working with angular v20
Angular version
20.0.0
PrimeNG version
v20
Node version
20.19.4
Browser(s)
Chrome Versión 142.0.7444.176
Steps to reproduce the behavior
- Add splitbutton to template 2. create function that returns your MenuItem[](your menu) 3. Pass that function to model attribute 4. Buttons in dropdown will not work
Expected behavior
The button should be clickable, and the model should be able to receive a MenuItem array through a function return
SplitButton uses TieredMenu under the hood.
For MenuItems containing routerLink-property will create an Angular RouterLink. But since the Stackblitz Example has no Angular Router Setup, it will throw a Dependency Injection Error (multiple times because of ChangeDetection + Non-Signal Function call):
SplitButton uses TieredMenu under the hood. For MenuItems containing `routerLink`-property will create an Angular RouterLink. But since the Stackblitz Example has no Angular Router Setup, it will throw a Dependency Injection Error (multiple times because of ChangeDetection + Non-Signal Function call):
![]()
HI,
Thanks for the feedback, I removed the items that used routerlink since they are not necessary to reproduce the error. I made it simplier and just using labels and commands. The bug is still ocurring. Stackblitz updated
That's actually a seperate issue due to ChangeDetection and Re-Rendering:
Zone.js triggers ChangeDetection on almost any Events or Event-Listeners regarding HTML-Elements.
TieredMenuSub has internal actions on hover:
https://github.com/primefaces/primeng/blob/c903ce36b661327ce076fbbe2442c8ad6197e47f/packages/primeng/src/tieredmenu/tieredmenu.ts#L363
Which in turn propagates ChangeDetection and Re-Render. getMenuItems is executed -> New Array-Instance passed to SplitButton options -> TieredMenu creates new TieredMenuSub Instances -> Hovering over an item triggers new ChangeDetection cycle
Here a demonstration: Calling a regular function causes infinite CD, because the the bound reference isn't stable. But computed signals retain values when no reactive dependencies are changing: https://stackblitz.com/edit/efczrox7-vdiev4kt?file=src%2Fapp%2Fsplit-button-basic-demo.ts
Passing a function returning items is not a good idea because of change detection concerns.
Declaring a dedicated property and passing this one solves the issue:
public menuItems = signal<MenuItem[]>(this.getMenuItems());
<p-splitbutton label="Save" (onClick)="save()" [model]="menuItems()" />
SplitButton uses TieredMenu under the hood. For MenuItems containing `routerLink`-property will create an Angular RouterLink. But since the Stackblitz Example has no Angular Router Setup, it will throw a Dependency Injection Error (multiple times because of ChangeDetection + Non-Signal Function call):