Remove specific index element from listView

Hi @david.mays and @Vinkal ,

Thank you for sharing your thoughts here. The solution is very useful.
In my use case, there's still one thing I couldn't figure out and would like to ask for your advice. The listview needs to be reset (back to 1 row with empty input) whenever the user opens the modal with the listview. I tried to create a javascript to set all the temp states to the initial values and retrigger the refillForm.

tempNumRows.setValue(1);
tempData.setValue({"rows":[{"name":null}]});

refillForm.trigger();

Though the listview row is back to only one row, the value entered in the name input is not cleared. Not sure how to fix the problem.
Please let me know if you have any thoughts on this. Thank you.

hi @doris.l
I think you can clear that input by using javascript as textInput1.setValue('').
I hope this could help you!

Thank you for reaching out.
Regards, Vinkal

Hi @Vinkal,

Thank you for replying. Using setValue to control the components in the listview doesn't work.

@doris.l I'm not sure i this is the best solution, but would it work if you made your script async? Something like:

await tempNumRows.setValue(1);
await tempData.setValue({"rows":[{"name":null}]});

await refillForm.trigger();

This way, refillForm.trigger() is not called until both relevant values are already set.

Curious to know if this solution works for you, keep me posted!

Hi @david.mays,

Thank you so much for the reply. I just tried the method. The actual result is: the row number on the listview turns back to one. The tempData returns to {"rows":[{"name":null}]}. But the value in the first row's textInput still stays even if I manually trigger refillForm.

What components do you have within your listview, and what is your full refillForm script?

Is it possible you did not add setValue statements in refillForm for the various components you have?

Hi David,
I have a select component and a textInput component per row. The refillForm script is here.

for (let i = 0; i < Object.keys(tempData.value.rows).length; i++) {
  // create a setValue statement for each nested component you need to fill
  select1[i].setValue(tempData.value.rows[i].type);
  textInput1[i].setValue(tempData.value.rows[i].note);
};

Oh, okay.

Then I think the value you're setting tempData to is incorrect. You'll need to include the keys of the values you're trying to set in refillForm, something like:

tempNumRows.setValue(1);
tempData.setValue({"rows":[{"type":null, "note":null}]});

refillForm.trigger();

Or, if you find that the value is not set properly before refillForm.trigger(), I think you can try the async method I suggested above, with the updated value in tempData.setValue(...):

await tempNumRows.setValue(1);
await tempData.setValue({"rows":[{"type":null, "note":null}]});

await refillForm.trigger();

Hi David,

Sorry I didn't explain things clearly before. I used the {row:[ {"name":null}]} just to align with the original post discussion. The real codes I'm using is the same as you suggested. I have used the codes with or without await in a new javascript to clear out the inputs in the listView but it didn't work out. :sweat_smile:

tempNumRows.setValue(1);
tempData.setValue({"rows":[{"type":null, "note":null}]});
refillForm.trigger();

Sorry I couldn't be more helpful!

I think you mentioned that the listView is also nested within a Modal, is that right? Does the listView refill properly if you take it out of the modal?

Another thing worth trying is, for this script:

tempNumRows.setValue(1);
tempData.setValue({"rows":[{"type":null, "note":null}]});
refillForm.trigger();

Go to the Advanced Options and check the box that says "Keep variable references inside the query in sync with your app" (see screenshot for an example).

I'm still not sure if this will solve your problem, but I saw the option and think it's worth a shot!

1 Like

Hi @david.mays,

Checking "Keep variable references inside the query in sync with your app" doesn't work for me. But I got some inspiration from your javascript scripts and figured out a way to reset the listview components.
Just want to say thank you again for providing so much help along the way.

I would be very interest in hearing what your solution was. Iā€™m running into the same problem! :blush:

This is a fantastic solution! Thank you!

It's great to see everyone chipping in to help solve this! :star_struck:

If the above solution has not worked for you, here's another workaround I've come up with that may help. It basically has the "Remove" button perform 2 Event Handlers:

  • Decrement the number from your temporary state that fills your ListView> Number of Rows
  • Make a copy of your ListView data. Use the JS method splice() and removes the data from your current textInputs using the specific ListView index(aka: "your row"), and set the value of the temporary state holding your existing data that no longer contains the deleted row.

Exported app:
delete_specific_listview_row.json (8.7 KB)

2 Likes

Hey all - think I came up with another (pretty similar to Kenny's) solution for this and wanted to drop it in:

  • In your initial query that is used as a source for the list view, say getData, with an event handler, set a temporary state state1 to getData.data (My data is a JSON that has an array inside of it I use for the listView)
  • Use state1 as the reference point for all elements within your listView, using i as normal.
  • Add another JS query removeElementOfListView, with the following code:
state1.value.line_items.splice(i,1)
state1.setValue(state1.value)
  • Create a "Remove" button in the listView and set to trigger removeElementOfListView

This seems to be working fine for me so far, but if you have changes in another element of the list, you will probably have to write those changes to state1 as they happen or they get reset when you remove a different element. (Haven't done that yet).

Seems to be working well for me! Thank you.

Hi @Kenny

What about file inputs, they don't have setValue method... Any approach for this case?

That's a good question @Doglas :thinking: file inputs are tricky because when they reset when they re-render (i.e. with any change to the listview's underlying state).

If you'll be dealing with a relatively small number of items, you can try fixing the listview's length to be the maximum number of items that could be in the listview:

Then, you could still use a temp state to define the rows as normal but instead of deleting a row you could set its value to be null:

And then nest your components in a container that you conditionally hide based on whether there's any data present for that row with something like {{!dataSource.value[i]}}:

That limits the amount of interaction anyone can have with the listview before needing to "reset" it so it's far from an ideal workaround :disappointed: but it may work if usage is limited enough and you could reset in on submission or so:

Curious to know what you think and maybe get more information about your use case!
hide_listview_items.json