Import
import { Iterate } from '@dnb/eufemia/extensions/forms'render(<Iterate.Array />)
Description
Iterate.Array works in many ways similar to field-components. It has a value-property that can receive an array or you can give it a path if you want it to retrieve an array from a surrounding DataContext. All children components of Iterate.Array are rendered once per item the array-value consists of.
import { Iterate, Field } from '@dnb/eufemia/extensions/forms'render(<Iterate.Arraylabel="Array label"value={['Iron Man', 'Captain America', 'The Hulk']}><Field.String itemPath="/" /></Iterate.Array>,)
About itemPath and path
itemPath points to the root of each iterated item, while path
points to the root of the data source:
import { Iterate, Field, Form } from '@dnb/eufemia/extensions/forms'render(<Form.HandlerdefaultData={{listOfHeroes: [{ name: 'Iron Man' },{ name: 'Captain America' },{ name: 'The Hulk' },],}}onChange={console.log}><Iterate.Array path="/listOfHeroes"><Field.Name.Last itemPath="/name" /></Iterate.Array></Form.Handler>,)
Individual values and dynamic paths
Since Iterate.Array renders its children once per item, the field components inside must receive values based on the different items in the array. This can be done in two ways:
1. itemPath
If field components inside Iterate.Array are given an itemPath property, this will look for values based on the array item being the root of the structure, even if the array often comes from a surrounding data set. This means that you do not need to think about which index the field should point to, because it is handled by Iterate.Array internally. You can look at the individual item as its own structure.
2. Function callback as children (render property)
If you want to be able to provide values to the individual field component directly instead of pointing to them with paths, you can give Iterate.Array a render property. It works a bit like an array-map call. The render function provides the value of the item as the first argument, the index of which item you are on as the second, and the internal array as the third.
render(<Iterate.Array path="/listOfHeroes">{(itemValue, itemIndex, internalArray) => {return <Field.Name.Last itemPath="/name" />}}</Iterate.Array>,)
You can also get the index by using the useItem hook:
const MyItem = () => {const { index } = Iterate.useItem()return <Field.Name.Last itemPath="/name" />}render(<Iterate.Array path="/listOfHeroes"><MyItem /></Iterate.Array>,)
The item number in labels
You can use the {itemNo} variable in the label to display the current item number. This is useful when you have a list of items and you want to display the item number in the label.
import { Iterate, Field } from '@dnb/eufemia/extensions/forms'render(<Iterate.Array value={['foo', 'bar']}><Field.String itemPath="/" label="Item no. {itemNo}" /></Iterate.Array>,)
The Iterate.ViewContainer and the Iterate.EditContainer also supports {itemNo} in the title property to display the current item number.
import { Iterate, Field } from '@dnb/eufemia/extensions/forms'render(<Iterate.Array value={['foo', 'bar']}><Iterate.ViewContainer title="Item no. {itemNo}">...</Iterate.ViewContainer></Iterate.Array>,)
Initial container mode
This section describes the behavior of the EditContainer and the ViewContainer components.
By default, the container mode is set to auto. This means that the container will open (switch to edit mode) when there is an error in the container or the value is falsy (empty string, null, undefined, etc.).
When a new item is added via the Iterate.PushButton component, the item before it will change to view mode, if it had no validation errors.
Filter data
You can filter data by paths specific or all paths.
/myList/0will filter out the first item of the list, includingfooandbar./myList/1/foowill filter outfooinside the second item of the list./myList/*/foowill filter out allfooobject keys from all items of the list./myList/*/subList/*/foodoes support multi wildcard paths.
In the example below, the data given in onSubmit will still have "foo2" and "bar2" of the list.
import { Iterate, Form, Field } from '@dnb/eufemia/extensions/forms'const myFilter = {'/myList/0': false,}render(<Form.Handlerdata={{myList: [{ foo: 'foo1', bar: 'bar1' },{ foo: 'foo2', bar: 'bar2' },],}}onSubmit={(data, { filterData }) => {console.log('onSubmit', filterData(myFilter))}}><Iterate.Array path="/myList"><Field.String itemPath="/foo" label="Foo no. {itemNo}" /><Field.String itemPath="/bar" label="Bar no. {itemNo}" /></Iterate.Array></Form.Handler>,)
Instead of false you can provide a function that returns false based on your logic.