@@ -45,14 +45,21 @@ export const useDeepValues = (
4545) => {
4646 const api = useApi ( ) ;
4747 const finalValues = ref < Record < string , any > > ( { } ) ;
48+ let fieldCache : Record < string , any > = { } ;
49+ let itemCache : Record < string , any > = { } ;
4850 // Directus store o2m value as reference so when o2m updated, val & oldVal in watch are the same.
4951 // This will serialize values so when o2m fields are updated, their changes can be seen.
50- const cloneValues = computed ( ( ) => JSON . stringify ( values . value ) ) ;
52+ const cloneValues = computed ( ( ) => JSON . stringify (
53+ values . value ,
54+ ( k , v ) => v === undefined ? null : v , // convert all undefined values to null to prevent JSON.stringify from removing their keys
55+ ) ) ;
5156
5257 watch (
5358 cloneValues ,
5459 async ( val , oldVal ) => {
55- if ( ! shouldUpdate ( template , computedField , JSON . parse ( val ) , JSON . parse ( oldVal ) ) ) {
60+ const valObj = JSON . parse ( val ) ;
61+ const oldValObj = oldVal !== undefined ? JSON . parse ( oldVal ) : { } ;
62+ if ( ! shouldUpdate ( template , computedField , valObj , oldValObj ) ) {
5663 return ;
5764 }
5865
@@ -68,17 +75,25 @@ export const useDeepValues = (
6875 const isM2O = relation . collection === collection ;
6976 const fieldName = isM2O ? relation . meta ?. many_field : relation . meta ?. one_field ;
7077
71- let fieldChanges = values . value [ fieldName ! ] as IRelationUpdate ;
72- if ( ! fieldChanges ) {
73- continue ;
74- }
78+ let fieldChanges = values . value [ fieldName ! ] as IRelationUpdate ?? {
79+ create : [ ] ,
80+ update : [ ] ,
81+ delete : [ ] ,
82+ } ;
7583
7684 let arrayOfIds : ( string | number ) [ ] = [ ] ;
7785 let arrayOfData : unknown [ ] = [ ] ;
7886
7987 if ( isM2O ) {
8088 if ( typeof fieldChanges === 'number' || typeof fieldChanges === 'string' ) {
8189 fieldChanges = { update : [ { id : fieldChanges } ] } ;
90+
91+ if ( typeof oldValObj [ key ] === 'object' ) {
92+ // When saving, fieldChanges will return to the initial value.
93+ // We must clear cache to obtain the new value after saving.
94+ fieldCache = { } ;
95+ itemCache = { } ;
96+ }
8297 } else if ( typeof fieldChanges === 'object' ) {
8398 if ( 'id' in fieldChanges ) {
8499 fieldChanges = { update : [ fieldChanges as { id : number | string } ] } ;
@@ -87,15 +102,26 @@ export const useDeepValues = (
87102 }
88103 }
89104 } else {
105+ if ( fieldChanges instanceof Array && ! ( oldValObj [ key ] instanceof Array ) ) {
106+ // When saving, fieldChanges will return to the initial value.
107+ // We must clear cache to obtain the new value after saving.
108+ fieldCache = { } ;
109+ itemCache = { } ;
110+ }
111+
90112 if ( pk !== '+' ) {
91- const {
92- data : { data } ,
93- } = await api . get ( `items/${ collection } /${ pk } ` , {
94- params : {
95- fields : [ key ] ,
96- } ,
97- } ) ;
98- arrayOfIds = arrayOfIds . concat ( data [ key ] ) ;
113+ let data ;
114+ if ( key in fieldCache ) {
115+ data = fieldCache [ key ] ;
116+ } else {
117+ data = ( await api . get ( `items/${ collection } /${ pk } ` , {
118+ params : {
119+ fields : [ key ] ,
120+ } ,
121+ } ) ) . data . data [ key ] ;
122+ fieldCache [ key ] = data ;
123+ }
124+ arrayOfIds = arrayOfIds . concat ( data ) ;
99125 }
100126
101127 if ( fieldChanges . delete ) {
@@ -109,18 +135,32 @@ export const useDeepValues = (
109135
110136 if ( arrayOfIds . length ) {
111137 const relatedCollection = isM2O ? relation . related_collection : relation . collection ;
138+ const path = relatedCollection === 'directus_users' ? '/users' : `items/${ relatedCollection } ` ;
112139
113- const {
114- data : { data } ,
115- } = await api . get ( `items/${ relatedCollection } ` , {
116- params : { filter : { id : { _in : arrayOfIds } } } ,
117- } ) ;
118-
119- // merging item updates
120- arrayOfData = data . map ( ( item : any ) => ( {
121- ...item ,
122- ...fieldChanges . update ?. find ( ( { id } ) => item . id === id ) ,
123- } ) ) ;
140+ if ( relatedCollection ) {
141+ let data ;
142+ if ( relatedCollection in itemCache && arrayOfIds . every ( id => id in itemCache [ relatedCollection ] ) ) {
143+ data = arrayOfIds . map ( id => itemCache [ relatedCollection ] [ id ] ) ;
144+ } else {
145+ data = ( await api . get ( path , {
146+ params : { filter : { id : { _in : arrayOfIds } } } ,
147+ } ) ) . data . data ;
148+ }
149+
150+ // merging item updates
151+ arrayOfData = data . map ( ( item : any ) => {
152+ if ( relatedCollection in itemCache ) {
153+ itemCache [ relatedCollection ] [ item . id ] = item ;
154+ } else {
155+ itemCache [ relatedCollection ] = { [ item . id ] : item } ;
156+ }
157+
158+ return {
159+ ...item ,
160+ ...fieldChanges . update ?. find ( ( { id } ) => item . id === id ) ,
161+ } ;
162+ } ) ;
163+ }
124164 }
125165
126166 // must concat after request, created items doenst have ids
@@ -135,6 +175,7 @@ export const useDeepValues = (
135175 } ,
136176 {
137177 deep : false ,
178+ immediate : true ,
138179 }
139180 ) ;
140181
0 commit comments