Here is the end goal, a list of textfields to which you can add and remove items. We want to have this as a component that can be reused or even generated dynamically without having to create new App State Variables each time (i.e. this would be useful for a training app where you add exercises that each have multiple sets):
To achieve this, you will need to create 2 components: 1 component will be a row and the other will be a ListView that will contain the first component we create (row component) as a dynamically generated child. The dynamically generated childs will be generated from a component state variable that we will create for our second component (the ListView component). Let's start with the row component.
Step 1:
1.1 Create a component that will contain a textfield and a delete icon.
1.2 Add 3 component parameters (initalValue <string>, deleteAction<action>, updateAction<action>)
1.3 For the textfield, assign the initial value as a if/else based on the "component parameter" initialValue. If set and not empty, use it, otherwise set textfield to "emptyString":
1.4 Assign the updateAction to the textField for "onChange":
1.5 Assign the deleteAction to the delete icon:
Step 2
note: for my particular use case, I need to pass an initial list of call types that have been previously set by the user. I want to display those first and then let the user add, remove or edit.
2.1 Create a new component with a listView and 2 buttons (one for the "add" action and one for "save"). Insert the component we created in step 1 as a child to the list view
2.2 Create "component parameters". One is a list of string (initial items to show) and the second is a "saveAction" for our save button.
2.3 Create a "component state variable" as a list of string. This will hold our dynamic list of rows:
2.4 In order to show our existing items at first, create a "On initialization" action for this component. As soon as the component initializes, we want to update the "local component state variable" to equal the "component parameter" that will pass from the page where we will use this component. This will set our initial list to the existing items:
2.5 Generate the listView child dynamically from the component state variable:
2.6 Create an action to "update component state variable" and add an item (empty string) when clicking the add button:
2.7 THIS PORTION IS KEY. We will pass the required parameters to our row component AND we will assign a unique Key. Assigning a unique key will allow us to read what value is entered in the child textfield. For this case, use the index in the listview as they "unique key":
2.8 Pass the initial value for the textfield, which is just the listview item:
2.9 Pass the "deleteAction" which will be a "update component state variable" where we delete an item at a specific index (the index of that item in the listview):
2.10 Pass the "updateAction" which is also a "update component state variable". We will update the value at the index (the same index as the one from listView). Because we assigned a unique Key in step 2.7, we will now have access to the textfield value
2.11 You can pass a "saveAction" as a component parameter for your save button and add it to your button "on tap"
Congrats! You now have a listview component that can be used on a page or even generated dynamically inside another listview. All that is left to do is to use this listview component somewhere and pass the "initialList" list and the "saveAction" action. Hope this helps!