11import { BoolCodeControl , StringControl } from "comps/controls/codeControl" ;
22import { clickEvent , eventHandlerControl } from "comps/controls/eventHandlerControl" ;
3+ import { valueComp } from "comps/generators" ;
34import { list } from "comps/generators/list" ;
45import { parseChildrenFromValueAndChildrenMap , ToViewReturn } from "comps/generators/multi" ;
5- import { withDefault } from "comps/generators/simpleGenerators" ;
6+ import { migrateOldData , withDefault } from "comps/generators/simpleGenerators" ;
67import { disabledPropertyView , hiddenPropertyView } from "comps/utils/propertyUtils" ;
8+ import { genRandomKey } from "comps/utils/idGenerator" ;
79import { trans } from "i18n" ;
810import _ from "lodash" ;
911import { fromRecord , MultiBaseComp , Node , RecordNode , RecordNodeToValue } from "lowcoder-core" ;
@@ -18,6 +20,7 @@ const childrenMap = {
1820 hidden : BoolCodeControl ,
1921 disabled : BoolCodeControl ,
2022 active : BoolCodeControl ,
23+ itemKey : valueComp < string > ( "" ) ,
2124 onEvent : withDefault ( eventHandlerControl ( events ) , [
2225 {
2326 // name: "click",
@@ -35,6 +38,7 @@ type ChildrenType = {
3538 hidden : InstanceType < typeof BoolCodeControl > ;
3639 disabled : InstanceType < typeof BoolCodeControl > ;
3740 active : InstanceType < typeof BoolCodeControl > ;
41+ itemKey : InstanceType < ReturnType < typeof valueComp < string > > > ;
3842 onEvent : InstanceType < ReturnType < typeof eventHandlerControl > > ;
3943 items : InstanceType < ReturnType < typeof navListComp > > ;
4044} ;
@@ -72,6 +76,10 @@ export class NavItemComp extends MultiBaseComp<ChildrenType> {
7276 this . children . items . addItem ( value ) ;
7377 }
7478
79+ getItemKey ( ) : string {
80+ return this . children . itemKey . getView ( ) ;
81+ }
82+
7583 exposingNode ( ) : RecordNode < NavItemExposing > {
7684 return fromRecord ( {
7785 label : this . children . label . exposingNode ( ) ,
@@ -93,17 +101,42 @@ type NavItemExposing = {
93101 items : Node < RecordNodeToValue < NavItemExposing > [ ] > ;
94102} ;
95103
104+ // Migrate old nav items to ensure they have a stable itemKey
105+ function migrateNavItemData ( oldData : any ) : any {
106+ if ( ! oldData ) return oldData ;
107+
108+ const migrated = {
109+ ...oldData ,
110+ itemKey : oldData . itemKey || genRandomKey ( ) ,
111+ } ;
112+
113+ // Also migrate nested items recursively
114+ if ( Array . isArray ( oldData . items ) ) {
115+ migrated . items = oldData . items . map ( ( item : any ) => migrateNavItemData ( item ) ) ;
116+ }
117+
118+ return migrated ;
119+ }
120+
121+ const NavItemCompMigrate = migrateOldData ( NavItemComp , migrateNavItemData ) ;
122+
96123export function navListComp ( ) {
97- const NavItemListCompBase = list ( NavItemComp ) ;
124+ const NavItemListCompBase = list ( NavItemCompMigrate ) ;
98125
99126 return class NavItemListComp extends NavItemListCompBase {
100127 addItem ( value ?: any ) {
101128 const data = this . getView ( ) ;
102129 this . dispatch (
103130 this . pushAction (
104- value || {
105- label : trans ( "menuItem" ) + " " + ( data . length + 1 ) ,
106- }
131+ value
132+ ? {
133+ ...value ,
134+ itemKey : value . itemKey || genRandomKey ( ) ,
135+ }
136+ : {
137+ label : trans ( "menuItem" ) + " " + ( data . length + 1 ) ,
138+ itemKey : genRandomKey ( ) ,
139+ }
107140 )
108141 ) ;
109142 }
0 commit comments