Problems with array renderer in combination with custom file upload renderer (Angular)

Hello dear JsonForms community,

I am working on a project, where I want to introduce a custom image upload renderer, which offers a file chooser. After the image was chosen, an upload immediatly starts with the help of an injected angular service. When the upload has completed, an url string will be returned to the renderer and then placed in the data as a reference to the image. The Renderer also receives an upload progress and at the end uses the url to display the image. So far so good, but when using the file renderer in an array, problerms start to occure.

I´ve reproduced the problem in the angular seed project with mocked logic and also made a gif of the results:
JsonForms FileRenderer Problem

In the Clip you can see an array with 3 file renderers. The first one has already completed the upload and is displaying the image. The second one is in its initial state and no file has been chosen yet. For the third one I´m choosing an image and the upload starts immidiatly. While the upload is still going, I delete the second item of the array but it seems, like the third item has been deleted. Shortly after the completed image appears as a third element in the list.

I could already figure out, that the main problem is, that I introduced local states (upload progress, file, upload completion) to the file renderer, which are not passed to the jsonForms core. When all uploads have finished, it is no problem anymore to delete items out of the array.

Another Problem is the way, jsonforms handles the deletion of array items. In this example the renderer in the second array item was not destroyed, but reused and updated with the content of the previous third element (but still preserving the path and the id from the deleted second element). This makes it impossibles for me to store the local states (progress, file and upload completion) outside the renderer (e.g. in the angular store) and retrieve it with the id of the renderer.

My Question:
Is there a way to change the behavior of arrays when deleting elements out of it? If not is there a way to pass those extra information of the file renderer through the jsonforms core, when updating the array?

I also uploaded my prototype of the angular seed project to github to try it yourself:

Hi @chrisR,

I did not yet take a look at the code but yes, depending on the implementation I would definitely expect problems like this to occur. Because we don’t have any information about the array contents, our generic array renderers can not use a more specific key than the index.

In general I can see two different approaches to fix this issue:

  • Instead of only a custom file renderer, implement a custom file array renderer. Then the code is under your full control and you can handle the stateful renderers just fine
  • Adjust the custom file renderer to be stateless. This can for example be done by decoupling upload and render logic and storing all states within the data (or a separate data store or both). When an element is then deleted and therefore an existing renderer “takes over” the renderer will show the appropriate content.

Please let me know whether this generic comment is sufficient or whether you need more in-depth guidance.

1 Like

Thanks for your answer!

I also have thought about an implemention of a custom file array renderer. It seems like the best solution for me, because it would make it possible to destroy the array elements and not just update those elements generically with changed data.

Regarding the other approach (decoupling the state in a seperate store) there is still a problem:
The ID of the file renderers in the array is not reliable enough to use them as a reference in the seperate store. Example: When the IDs of the array items are [#1, #2, #3, #4] and you delete the #2, I would expect the remaining IDs to be [#1, #3, #4], but in reality they become [#1, #2, #3]

This is why I tend to prefer your first solution.

The ID of the file renderers in the array is not reliable enough to use them as a reference in the seperate store. Example: When the IDs of the array items are [#1, #2, #3, #4] and you delete the #2, I would expect the remaining IDs to be [#1, #3, #4], but in reality they become [#1, #2, #3]

Yes you can’t use the array item ids then. However what you could do is to update the data with, for example, status: 'uploading', id: '<random-id>', and then use that random id (which could also just be an incrementer) to refer to the entry.

If such an element is deleted the upload process referring to that id can be canceled. If an upload process is finished and successful the corresponding entry can be updated.

So basically introducing an id to decouple from array indices.

1 Like