1# wrapBuilder: Encapsulating Global @Builder 2 3When you use multiple global @Builder functions in a struct to implement different UI effects, the code maintenance becomes difficult and the page is not neat. In this case, you can use **wrapBuilder** to encapsulate the global @Builder. 4 5 Before reading this topic, you are advised to read [\@Builder](./arkts-builder.md). 6 7> **NOTE** 8> 9> This API is supported since API version 11. 10 11After the @Builder method assigns a value to a variable or array, the variable or array cannot be used in the UI method. 12 13```ts 14@Builder 15function builderElement() {} 16 17let builderArr: Function[] = [builderElement]; 18@Builder 19function testBuilder() { 20 ForEach(builderArr, (item: Function) => { 21 item(); 22 }) 23} 24``` 25 26In the preceding code, **builderArr** is an array consisting of @Builder methods. When each @Builder method is obtained from **ForEach**, the @Builder method cannot be used in the UI method. 27 28 To solve this problem, **wrapBuilder** is introduced as the global @Builder encapsulation function. **wrapBuilder** is a template function that accepts a [global \@Builder decorated function](arkts-builder.md#global-custom-builder-function) as its argument and returns a **WrappedBuilder** object, thereby allowing global \@Builder decorated function to be assigned a value and transferred. 29 30## Available APIs 31 32**wrapBuilder** is a template function that returns a **WrappedBuilder** object. 33 34```ts 35declare function wrapBuilder< Args extends Object[]>(builder: (...args: Args) => void): WrappedBuilder; 36``` 37The **WrappedBuilder** object is also a template class. 38 39```ts 40declare class WrappedBuilder< Args extends Object[]> { 41 builder: (...args: Args) => void; 42 43 constructor(builder: (...args: Args) => void); 44} 45``` 46 47 48>**NOTE**<br>The template parameter **Args extends Object[]** is a parameter list of the builder function to be wrapped. 49 50Example 51 52```ts 53let builderVar: WrappedBuilder<[string, number]> = wrapBuilder(MyBuilder) 54let builderArr: WrappedBuilder<[string, number]>[] = [wrapBuilder(MyBuilder)] // An array is acceptable. 55``` 56 57 58 59## Constraints 60 61**wrapBuilder** only accepts a [global \@Builder decorated function](arkts-builder.md#global-custom-builder-function) as its argument. 62 63Of the **WrappedBuilder** object it returns, the **builder** attribute method can be used only inside the struct. 64 65 66 67## Assigning a Value to a Variable Using the @Builder Method 68 69The **MyBuilder** method decorated by @Builder is used as the parameter of **wrapBuilder**, and **wrapBuilder** is assigned to the **globalBuilder** variable, which solves the problem that the @Builder method cannot be used after being assigned to the variable. 70 71```ts 72@Builder 73function MyBuilder(value: string, size: number) { 74 Text(value) 75 .fontSize(size) 76} 77 78let globalBuilder: WrappedBuilder<[string, number]> = wrapBuilder(MyBuilder); 79 80@Entry 81@Component 82struct Index { 83 @State message: string = 'Hello World'; 84 85 build() { 86 Row() { 87 Column() { 88 globalBuilder.builder(this.message, 50) 89 } 90 .width('100%') 91 } 92 .height('100%') 93 } 94} 95``` 96 97## Assigning a Value to a Variable by the @Builder Method to Use the Variable in UI Syntax 98 99In this example, the custom component **Index** uses **ForEach** to render different \@Builder functions. You can use the **wrapBuilder** array declared in **builderArr** to present different \@Builder function effects. In this way, the code is neat. 100 101``` 102@Builder 103function MyBuilder(value: string, size: number) { 104 Text(value) 105 .fontSize(size) 106} 107 108@Builder 109function YourBuilder(value: string, size: number) { 110 Text(value) 111 .fontSize(size) 112 .fontColor(Color.Pink) 113} 114 115const builderArr: WrappedBuilder<[string, number]>[] = [wrapBuilder(MyBuilder), wrapBuilder(YourBuilder)]; 116 117 118@Entry 119@Component 120struct Index { 121 @Builder testBuilder() { 122 ForEach(builderArr, (item: WrappedBuilder<[string, number]>) => { 123 item.builder('Hello World', 30) 124 } 125 126 ) 127 } 128 129 build() { 130 Row() { 131 Column() { 132 this.testBuilder() 133 } 134 .width('100%') 135 } 136 .height('100%') 137 } 138} 139``` 140 141## Passing Parameters by Reference 142 143If parameters are passed in by reference, the UI re-rendering is triggered. 144 145```ts 146class Tmp { 147 paramA2: string = 'hello'; 148} 149 150@Builder function overBuilder(param: Tmp) { 151 Column(){ 152 Text(`wrapBuildervalue:${param.paramA2}`) 153 } 154} 155 156const wBuilder: WrappedBuilder<[Tmp]> = wrapBuilder(overBuilder); 157 158@Entry 159@Component 160struct Parent{ 161 @State label: Tmp = new Tmp(); 162 build(){ 163 Column(){ 164 wBuilder.builder({paramA2: this.label.paramA2}) 165 Button('Click me').onClick(() => { 166 this.label.paramA2 = 'ArkUI'; 167 }) 168 } 169 } 170} 171``` 172 173## FAQs 174 175### wrapBuilder Redefinition Failure 176 177In the same custom component, the same **wrapBuilder** can be initialized only once. In the example, after **builderObj** is initialized through **wrapBuilder(MyBuilderFirst)**, **wrapBuilder(MyBuilderSecond)** does not take effect when a value is assigned to **builderObj** again. 178 179```ts 180@Builder 181function MyBuilderFirst(value: string, size: number) { 182 Text('MyBuilderFirst: ' + value) 183 .fontSize(size) 184} 185 186@Builder 187function MyBuilderSecond(value: string, size: number) { 188 Text('MyBuilderSecond: ' + value) 189 .fontSize(size) 190} 191 192interface BuilderModel { 193 globalBuilder: WrappedBuilder<[string, number]>; 194} 195 196@Entry 197@Component 198struct Index { 199 @State message: string = 'Hello World'; 200 @State builderObj: BuilderModel = { globalBuilder: wrapBuilder(MyBuilderFirst) }; 201 202 aboutToAppear(): void { 203 setTimeout(() => { 204 // wrapBuilder (MyBuilderSecond) does not take effect. 205 this.builderObj.globalBuilder = wrapBuilder(MyBuilderSecond); 206 },1000) 207 } 208 209 build() { 210 Row() { 211 Column() { 212 this.builderObj.globalBuilder.builder(this.message, 20) 213 } 214 .width('100%') 215 } 216 .height('100%') 217 } 218} 219``` 220