• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# ForEach
2
3
4The development framework provides ForEach to iterate arrays and create components for each array item. ForEach is defined as follows:
5
6
7
8```
9ForEach(
10    arr: any[], // Array to be iterated
11    itemGenerator: (item: any, index?: number) => void, // child component generator
12    keyGenerator?: (item: any, index?: number) => string // (optional) Unique key generator, which is recommended.
13)
14```
15
16
17## ForEach
18
19
20ForEach(arr: any[],itemGenerator: (item: any, index?: number) => void, keyGenerator?: (item: any, index?: number) => string):void
21
22
23  Table1 Parameters
24
25| Name | Type | Mandatory | Default Value | Description |
26| -------- | -------- | -------- | -------- | -------- |
27| arr | any[] | Yes | - | Must be an array. An empty array is allowed. If an array is empty, no child component is created. You can set the functions whose return values are of the array type, for example, arr.slice (1, 3). The set functions cannot change any state variables including the array itself, such as Array.splice, Array.sort, and Array.reverse. |
28| itemGenerator | (item: any, index?: number) => void | Yes | - | Used to generate the lambda function of the child components. It generates one or more child components for a given array item. A single component and its child component list must be contained in braces ({...}) |
29| keyGenerator | (item: any, index?: number) => string | No | - | Used as an anonymous parameter for generating a unique and stable key value for a given array item. When the position of a subitem in the array is changed, the key value of the subitem cannot be changed. When a subitem in the array is replaced with a new item, the key value of the current item must be different from that of the new item. This key-value generator is optional. However, for performance reasons, it is strongly recommended that the key-value generator be provided, so that the development framework can better identify array changes. If the array is reversed while no key-value generator is provided, all nodes in ForEach will be rebuilt. |
30
31
32> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**:
33> - ForEach must be used in container components.
34>
35> - The generated child components are allowed in the parent container component of ForEach. The child component generator function can contain the if/else conditional statement, and the if/else conditional statement can contain ForEach.
36>
37> - The calling sequence of subitem generator functions may be different from that of the data items in the array. During the development, do not assume whether the subitem generator and key value generator functions are executed and the execution sequence. The following is an example of incorrect usage:
38>
39>   ```
40>   ForEach(anArray, item => {Text(`${++counter}. item.label`)})
41>   ```
42>
43>   Below is an example of correct usage:
44>
45>
46>   ```
47>   ForEach(anArray.map((item1, index1) => { return { i: index1 + 1, data: item1 }; }),
48>           item => Text(`${item.i}. item.data.label`),
49>           item => item.data.id.toString())
50>   ```
51
52
53## Example
54
55The following is an example of a simple-type array:
56
57
58```
59@Entry
60@Component
61struct MyComponent {
62    @State arr: number[] = [10, 20, 30]
63    build() {
64        Column() {
65            Button() {
66                Text('Reverse Array')
67            }.onClick(() => {
68                this.arr.reverse()
69            })
70
71            ForEach(this.arr,                         // Parameter 1: array to be iterated
72                    (item: number) => {               // Parameter 2: item generator
73                        Text(`item value: ${item}`)
74                        Divider()
75                    },
76                    (item: number) => item.toString() // Parameter 3: unique key generator, which is optional but recommended.
77            )
78        }
79    }
80}
81```
82
83  The following is an example of a complex-type array:
84
85```
86class Month {
87  year: number
88  month: number
89  days: Array<number>
90
91  constructor(year, month, days) {
92    this.year = year;
93    this.month = month;
94    this.days = days;
95  }
96}
97
98@Entry
99@Component
100struct Calendar1 {
101// simulate with 6 months
102  @State calendar: Month[] = [
103    new Month(2020, 1, [...Array(31).keys()]),
104    new Month(2020, 2, [...Array(28).keys()]),
105    new Month(2020, 3, [...Array(31).keys()]),
106    new Month(2020, 4, [...Array(30).keys()]),
107    new Month(2020, 5, [...Array(31).keys()]),
108    new Month(2020, 6, [...Array(30).keys()]),
109  ]
110
111  build() {
112    Column() {
113      Button('next month')
114        .onClick(() => {
115          this.calendar.shift()
116          this.calendar.push({
117            year: 2020,
118            month: 7,
119            days: [...Array(31)
120              .keys()]
121          })
122        })
123      ForEach(this.calendar,
124        (item: Month) => {
125          Text('month:' + item.month)
126            .fontSize(30)
127            .padding(20)
128          Grid() {
129            ForEach(item.days,
130              (day: number) => {
131                GridItem() {
132                  Text((day + 1).toString())
133                    .fontSize(30)
134                }
135              },
136              (day: number) => day.toString())
137          }
138          .columnsTemplate('1fr 1fr 1fr 1fr 1fr 1fr 1fr')
139          .rowsGap(20)
140        },
141        // field is used together with year and month as the unique ID of the month.
142        (item: Month) => (item.year * 12 + item.month).toString())
143    }
144  }
145}
146```
147