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
6> **NOTE**
7>
8> This API is supported since API version 11.
9
10After the @Builder method assigns a value to a variable or array, the variable or array cannot be used in the UI method.
11
12```ts
13@Builder
14function builderElement() {}
15
16let builderArr: Function[] = [builderElement];
17@Builder
18function testBuilder() {
19  ForEach(builderArr, (item: Function) => {
20    item();
21  })
22}
23```
24
25In 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.
26
27 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.
28
29## Available APIs
30
31**wrapBuilder** is a template function that returns a **WrappedBuilder** object.
32
33```ts
34declare function wrapBuilder< Args extends Object[]>(builder: (...args: Args) => void): WrappedBuilder;
35```
36The **WrappedBuilder** object is also a template class.
37
38```ts
39declare class WrappedBuilder< Args extends Object[]> {
40  builder: (...args: Args) => void;
41
42  constructor(builder: (...args: Args) => void);
43}
44```
45
46
47>**NOTE**<br>The template parameter **Args extends Object[]** is a parameter list of the builder function to be wrapped.
48
49Example
50
51```ts
52let builderVar: WrappedBuilder<[string, number]> = wrapBuilder(MyBuilder)
53let builderArr: WrappedBuilder<[string, number]>[] = [wrapBuilder(MyBuilder)] // An array is acceptable.
54```
55
56## Constraints
57
58**wrapBuilder** only accepts a [global \@Builder decorated function](arkts-builder.md#global-custom-builder-function) as its argument.
59
60Of the **WrappedBuilder** object it returns, the **builder** attribute method can be used only inside the struct.
61
62## Assigning a Value to a Variable Using the @Builder Method
63
64The **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.
65
66```ts
67@Builder
68function MyBuilder(value: string, size: number) {
69  Text(value)
70    .fontSize(size)
71}
72
73let globalBuilder: WrappedBuilder<[string, number]> = wrapBuilder(MyBuilder);
74
75@Entry
76@Component
77struct Index {
78  @State message: string = 'Hello World';
79
80  build() {
81    Row() {
82      Column() {
83        globalBuilder.builder(this.message, 50)
84      }
85      .width('100%')
86    }
87    .height('100%')
88  }
89}
90```
91
92##  Assigning a Value to a Variable by the @Builder Method to Use the Variable in UI Syntax
93
94In 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.
95
96```
97@Builder
98function MyBuilder(value: string, size: number) {
99  Text(value)
100    .fontSize(size)
101}
102
103@Builder
104function YourBuilder(value: string, size: number) {
105  Text(value)
106    .fontSize(size)
107    .fontColor(Color.Pink)
108}
109
110const builderArr: WrappedBuilder<[string, number]>[] = [wrapBuilder(MyBuilder), wrapBuilder(YourBuilder)];
111
112
113@Entry
114@Component
115struct Index {
116  @Builder testBuilder() {
117    ForEach(builderArr, (item: WrappedBuilder<[string, number]>) => {
118      item.builder('Hello World', 30)
119    }
120
121    )
122  }
123
124  build() {
125    Row() {
126      Column() {
127        this.testBuilder()
128      }
129      .width('100%')
130    }
131    .height('100%')
132  }
133}
134```
135
136## Passing Parameters by Reference
137
138If parameters are passed in by reference, the UI re-rendering is triggered.
139
140```ts
141class Tmp {
142  paramA2: string = 'hello';
143}
144
145@Builder function overBuilder(param: Tmp) {
146  Column(){
147    Text(`wrapBuildervalue:${param.paramA2}`)
148  }
149}
150
151const wBuilder: WrappedBuilder<[Tmp]> = wrapBuilder(overBuilder);
152
153@Entry
154@Component
155struct Parent{
156  @State label: Tmp = new Tmp();
157  build(){
158    Column(){
159      wBuilder.builder({paramA2: this.label.paramA2})
160      Button('Click me').onClick(() => {
161        this.label.paramA2 = 'ArkUI';
162      })
163    }
164  }
165}
166```
167
168## Incorrect Usage
169
170### wrapBuilder Accepts Only a Global Function Decorated by @Builder
171
172```ts
173function MyBuilder() {
174
175}
176
177const globalBuilder: WrappedBuilder<[string, number]> = wrapBuilder(MyBuilder);
178
179@Entry
180@Component
181struct Index {
182  @State message: string = 'Hello World';
183
184  build() {
185    Row() {
186      Column() {
187        Text(this.message)
188          .fontSize(50)
189          .fontWeight(FontWeight.Bold)
190        globalBuilder.builder(this.message, 30)
191      }
192      .width('100%')
193    }
194    .height('100%')
195  }
196}
197```
198
199### wrapBuilder Redefinition Failure
200
201After **builderObj** is initialized and defined through **wrapBuilder(MyBuilderFirst)**, if you assign a new value to **builderObj**, **wrapBuilder(MyBuilderSecond)** does not take effect. Only the first defined **wrapBuilder(MyBuilderFirst)** takes effect.
202
203```ts
204@Builder
205function MyBuilderFirst(value: string, size: number) {
206  Text('MyBuilderFirst: ' + value)
207    .fontSize(size)
208}
209
210@Builder
211function MyBuilderSecond(value: string, size: number) {
212  Text('MyBuilderSecond: ' + value)
213    .fontSize(size)
214}
215
216interface BuilderModel {
217  globalBuilder: WrappedBuilder<[string, number]>;
218}
219
220@Entry
221@Component
222struct Index {
223  @State message: string = 'Hello World';
224  @State builderObj: BuilderModel = { globalBuilder: wrapBuilder(MyBuilderFirst) };
225
226  aboutToAppear(): void {
227    setTimeout(() => {
228      this.builderObj.globalBuilder = wrapBuilder(MyBuilderSecond);
229    },1000)
230  }
231
232  build() {
233    Row() {
234      Column() {
235        this.builderObj.globalBuilder.builder(this.message, 20)
236      }
237      .width('100%')
238    }
239    .height('100%')
240  }
241}
242```
243