@@ -114,6 +114,7 @@ import { useIcons } from '@/icons';
114114import {
115115 composePaths ,
116116 createDefaultValue ,
117+ mapStateToArrayControlProps ,
117118 type ControlElement ,
118119} from ' @jsonforms/core' ;
119120import {
@@ -128,6 +129,7 @@ import type {
128129 ColDef ,
129130 ColGroupDef ,
130131 FilterChangedEvent ,
132+ GetRowIdFunc ,
131133 GridApi ,
132134 GridOptions ,
133135 GridReadyEvent ,
@@ -139,6 +141,7 @@ import type {
139141 Theme ,
140142} from ' ag-grid-community' ;
141143import startCase from ' lodash/startCase' ;
144+ import uniqueId from ' lodash/uniqueId' ;
142145import {
143146 computed ,
144147 defineAsyncComponent ,
@@ -181,6 +184,7 @@ const AgGridVue = defineAsyncComponent(() =>
181184 RowSelectionModule,
182185 TextEditorModule,
183186 TextFilterModule,
187+ TooltipModule,
184188 ValidationModule,
185189 ModuleRegistry,
186190 themeQuartz,
@@ -199,6 +203,7 @@ const AgGridVue = defineAsyncComponent(() =>
199203 RowSelectionModule ,
200204 TextEditorModule ,
201205 TextFilterModule ,
206+ TooltipModule ,
202207 ValidationModule ,
203208 ]);
204209
@@ -213,6 +218,13 @@ function isColDef(col: ColDef | ColGroupDef): col is ColDef {
213218 return ! (' children' in col );
214219}
215220
221+ const rowIdSymbol = Symbol (' rowId' );
222+ function ensureRowId(row : object ) {
223+ if (! (row as any )[rowIdSymbol ]) {
224+ (row as any )[rowIdSymbol ] = uniqueId ();
225+ }
226+ }
227+
216228const components = {
217229 DispatchRendererCell: defineComponent ({
218230 name: ' DispatchRendererCell' ,
@@ -222,38 +234,45 @@ const components = {
222234 type: Object as PropType <
223235 ICellRendererParams & {
224236 propertyName: string ;
225- input: ReturnType <typeof useVuetifyArrayControl > &
226- ReturnType <typeof useJsonFormsArrayControl >;
237+ control: ReturnType <typeof mapStateToArrayControlProps >;
227238 }
228239 >,
229240 required: true ,
230241 },
231242 },
232243 setup({ params }) {
233244 return () => {
234- const { propertyName, node, input } = params ;
235-
236- const control = input .control ;
245+ const { propertyName, node, control } = params ;
237246 const controlWithoutLabel = (scope : string ): ControlElement => {
238247 return { type: ' Control' , scope: scope , label: false };
239248 };
240249
241250 function resolveUiSchema(propName : string ) {
242- return control .value . schema .properties && propName
251+ return control .schema .properties && propName
243252 ? controlWithoutLabel (` #/properties/${propName } ` )
244253 : controlWithoutLabel (' #' );
245254 }
246255
247256 return h (DispatchRenderer , {
248- schema: control .value . schema ,
257+ schema: control .schema ,
249258 uischema: resolveUiSchema (propertyName ),
250- path: composePaths (control .value . path , ` ${node .rowIndex } ` ),
251- enabled: control .value . enabled ,
252- renderers: control .value . renderers ,
253- cells: control .value . cells ,
259+ path: composePaths (control .path , ` ${node .sourceRowIndex } ` ),
260+ enabled: control .enabled ,
261+ renderers: control .renderers ,
262+ cells: control .cells ,
254263 });
255264 };
256265 },
266+ methods: {
267+ // ag grid will check if we have a refresh function that will return true then it will reuse the renderer instead of recreating it
268+ refresh(
269+ _params : ICellRendererParams <any , any , any > & {
270+ propertyName: string ;
271+ },
272+ ) {
273+ return true ;
274+ },
275+ },
257276 }),
258277};
259278
@@ -297,14 +316,38 @@ const AgGridArrayControlRenderer = defineComponent({
297316
298317 const suppressRowDrag = ref (! input .control .value .enabled );
299318
319+ const schema = ref (input .control .value .schema );
320+ watch (
321+ () => input .control .value .schema ,
322+ (newSchema ) => {
323+ schema .value = newSchema ;
324+ },
325+ );
326+ const showSortButtons = ref (input .appliedOptions .value .showSortButtons );
327+ watch (
328+ () => input .appliedOptions .value .showSortButtons ,
329+ (newValue ) => {
330+ showSortButtons .value = newValue ;
331+ },
332+ );
333+ const enabled = ref (input .control .value .enabled );
334+ watch (
335+ () => input .control .value .enabled ,
336+ (newValue ) => {
337+ enabled .value = newValue ;
338+ },
339+ );
340+
300341 const gridOptions = computed <GridOptions >(() => {
301342 const baseOptions: GridOptions =
302343 props .uischema ?.options ?.agGridOptions || {};
303344
304- const showSortButtons = ref ( input . appliedOptions . value . showSortButtons ) ;
345+ let haveRowDragColumn = false ;
305346 // Generate columnDefs from schema
306347 const schemaColumnDefs: ColDef [] = Object .entries (
307- input .control .value .schema .properties || {},
348+ schema .value .type === ' object'
349+ ? schema .value .properties || {}
350+ : { ' ' : { title: ' ' } }, // primitive
308351 ).map (([propertyName , propertySchema ]: [string , any ]) => {
309352 const baseDef: ColDef = {
310353 headerName: propertySchema .title ?? startCase (propertyName ),
@@ -320,7 +363,7 @@ const AgGridArrayControlRenderer = defineComponent({
320363
321364 if (isColDef (extraDef ) && extraDef .rowDrag ) {
322365 // another column is designated as reordering column
323- showSortButtons . value = false ;
366+ haveRowDragColumn = true ;
324367 }
325368
326369 const cellDef = isColDef (extraDef )
@@ -335,10 +378,13 @@ const AgGridArrayControlRenderer = defineComponent({
335378 component: ' DispatchRendererCell' ,
336379 params: {
337380 propertyName ,
338- input : input ,
381+ control : input . control . value ,
339382 },
340383 };
341384 },
385+ cellRendererParams: {
386+ deferRender: true ,
387+ },
342388 }
343389 : {};
344390
@@ -351,7 +397,7 @@ const AgGridArrayControlRenderer = defineComponent({
351397
352398 const schemaColumnDefsControls: ColDef [] = [];
353399
354- if (input . control . value . enabled && showSortButtons .value ) {
400+ if (enabled . value && showSortButtons .value && ! haveRowDragColumn ) {
355401 schemaColumnDefsControls .push ({
356402 headerName: ' ' ,
357403 rowDrag: true ,
@@ -364,6 +410,21 @@ const AgGridArrayControlRenderer = defineComponent({
364410 }
365411
366412 delete baseOptions .rowData ;
413+
414+ let getRowId: GetRowIdFunc | undefined = undefined ;
415+ if (schema .value .type === ' object' || schema .value .type === ' array' ) {
416+ getRowId = (params ) => {
417+ const data = params .data ;
418+ if (typeof data === ' object' && data !== null ) {
419+ ensureRowId (data );
420+ return (data as any )[rowIdSymbol ];
421+ } else {
422+ // fallback
423+ return String (data );
424+ }
425+ };
426+ }
427+
367428 return {
368429 ... baseOptions ,
369430 columnDefs: [... schemaColumnDefsControls , ... schemaColumnDefs ],
@@ -375,6 +436,7 @@ const AgGridArrayControlRenderer = defineComponent({
375436 },
376437 components ,
377438 suppressRowDrag: baseOptions .suppressRowDrag || suppressRowDrag .value ,
439+ getRowId: getRowId ,
378440 };
379441 });
380442
@@ -406,7 +468,7 @@ const AgGridArrayControlRenderer = defineComponent({
406468 };
407469
408470 const onRowDragEnd = (event : RowDragEndEvent ) => {
409- const fromIndex = event .node .rowIndex ?? - 1 ;
471+ const fromIndex = event .node .sourceRowIndex ?? - 1 ;
410472 const toIndex = event .overIndex ;
411473 if (fromIndex === - 1 || event .overIndex === - 1 || fromIndex === toIndex ) {
412474 return ;
0 commit comments