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>  **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