1e41f4b71Sopenharmony_ci# BuilderNode
2e41f4b71Sopenharmony_ci
3e41f4b71Sopenharmony_ci## Overview
4e41f4b71Sopenharmony_ci
5e41f4b71Sopenharmony_ciThe [BuilderNode](../reference/apis-arkui/js-apis-arkui-builderNode.md) provides the capability to mount built-in components. It creates component trees with a stateless UI method, the [global custom builder function](../quick-start/arkts-builder.md#global-custom-builder-function), which is decorated by @Builder, and accesses the root [FrameNode](../reference/apis-arkui/js-apis-arkui-frameNode.md) through [getFrameNode](../reference/apis-arkui/js-apis-arkui-builderNode.md#getframenode). This node can be directly returned by [NodeController](../reference/apis-arkui/js-apis-arkui-nodeController.md) and mounted under the [NodeContainer](../reference/apis-arkui/arkui-ts/ts-basic-components-nodecontainer.md) node. It also enables embedding declarative component structures within **FrameNode** and [RenderNode](../reference/apis-arkui/js-apis-arkui-renderNode.md) tree structures for mixed display capabilities. Additionally, the BuilderNode offers texture export functionality, with exported textures used for same-layer rendering in the [XComponent](../reference/apis-arkui/arkui-ts/ts-basic-components-xcomponent.md).
6e41f4b71Sopenharmony_ci
7e41f4b71Sopenharmony_ciThe BuilderNode enables the combination of ArkTS built-in component trees with custom nodes (such as FrameNodes and RenderNodes) for mixed display. It also allows built-in components to be embedded within third-party frameworks that use custom nodes.
8e41f4b71Sopenharmony_ci
9e41f4b71Sopenharmony_ciThe BuilderNode offers the capability to pre-create built-in components, enabling their initialization at customized times and dynamic mounting as needed in operations. This is particularly useful for reducing the initialization time of declarative components such as [Web](../reference/apis-arkweb/ts-basic-components-web.md) and [XComponent](../reference/apis-arkui/arkui-ts/ts-basic-components-xcomponent.md), which typically take longer to initialize.
10e41f4b71Sopenharmony_ci
11e41f4b71Sopenharmony_ci![en-us_image_builder-node](figures/builder-node.png)
12e41f4b71Sopenharmony_ci
13e41f4b71Sopenharmony_ciA BuilderNode can be used only as a leaf node. If an update is required, you are advised to use the update APIs provided by the BuilderNode, rather than making modifications directly to the RenderNode obtained from it.
14e41f4b71Sopenharmony_ci
15e41f4b71Sopenharmony_ci> **NOTE**
16e41f4b71Sopenharmony_ci> 
17e41f4b71Sopenharmony_ci> - The BuilderNode only supports a single [global custom build function(../quick-start/arkts-builder.md#global-custom-builder-function) decorated by @Builder and wrapped by [wrapBuilder](../quick-start/arkts-wrapBuilder.md).
18e41f4b71Sopenharmony_ci> 
19e41f4b71Sopenharmony_ci> - A newly created BuilderNode can only obtain a **FrameNode** object pointing to the root node through [getFrameNode](../reference/apis-arkui/js-apis-arkui-builderNode.md#getframenode) after [build](../reference/apis-arkui/js-apis-arkui-builderNode.md#build); otherwise, it returns **null**.
20e41f4b71Sopenharmony_ci> 
21e41f4b71Sopenharmony_ci> - If the root node of the passed Builder is a syntactic node (such as **if/else** and **ForEach**), an additional FrameNode must be generated, which will be displayed as "BuilderProxyNode" in the node tree.
22e41f4b71Sopenharmony_ci> 
23e41f4b71Sopenharmony_ci> - If BuilderNode mounts a node onto another FrameNode through **getFrameNode**, or mounts it as a child node onto a **NodeContainer**, the node uses the layout constraints of the parent component for layout.
24e41f4b71Sopenharmony_ci> 
25e41f4b71Sopenharmony_ci> - If a BuilderNode's FrameNode mounts its node onto a RenderNode through [getRenderNode](../reference/apis-arkui/js-apis-arkui-frameNode.md#getrendernode), its size defaults to **0** since its FrameNode is not yet part of the tree. To display it properly, you must explicitly specify the layout constraint size through [selfIdeaSize](../reference/apis-arkui/js-apis-arkui-builderNode.md#renderoptions) in the constructor.
26e41f4b71Sopenharmony_ci> 
27e41f4b71Sopenharmony_ci> - Pre-creation with the BuilderNode does not reduce the creation time of components. For the **Web** component, resources must be loaded in the kernel during creation, and pre-creation cannot reduce this time. However, it enables the kernel to preload resources, which can reduce the loading time when the component is used.
28e41f4b71Sopenharmony_ci
29e41f4b71Sopenharmony_ci## Creating a BuilderNode Object
30e41f4b71Sopenharmony_ci
31e41f4b71Sopenharmony_ciWhen creating a **BuilderNode** object, which is a template class, you must specify a type that matches the type of the [WrappedBuilder](../quick-start/arkts-wrapBuilder.md) used in the **build** method later on. Mismatches can cause compilation warnings and failures.
32e41f4b71Sopenharmony_ci
33e41f4b71Sopenharmony_ci## Creating a Built-in Component Tree
34e41f4b71Sopenharmony_ci
35e41f4b71Sopenharmony_ciUse the **build** API of **BuilderNode** to create a built-in component tree. The tree is constructed based on the **WrappedBuilder** object passed in, and the root node of the component tree is retained.
36e41f4b71Sopenharmony_ci
37e41f4b71Sopenharmony_ci> **NOTE**
38e41f4b71Sopenharmony_ci>
39e41f4b71Sopenharmony_ci> Stateless UI methods using the global @Builder can have at most one root node.
40e41f4b71Sopenharmony_ci>
41e41f4b71Sopenharmony_ci> The @Builder within the **build** method accepts only one input parameter.
42e41f4b71Sopenharmony_ci>
43e41f4b71Sopenharmony_ci> In scenarios where @Builder is nested within another @Builder in the **build** method, ensure that the parameters of the nested @Builder match the input parameters provided to the **build** method.
44e41f4b71Sopenharmony_ci> 
45e41f4b71Sopenharmony_ci> For scenarios where @Builder is nested within another @Builder, if the parameter types do not match, you must include the BuilderOptions](../reference/apis-arkui/js-apis-arkui-builderNode.md#buildoptions12) field as a parameter for the [build](../reference/apis-arkui/js-apis-arkui-builderNode.md#build12) method.
46e41f4b71Sopenharmony_ci
47e41f4b71Sopenharmony_ciCreate offline nodes and built-in component trees, and use them in conjunction with FrameNodes.
48e41f4b71Sopenharmony_ci
49e41f4b71Sopenharmony_ciThe root node of the BuilderNode is directly used as the return value of [makeNode](../reference/apis-arkui/js-apis-arkui-nodeController.md#makenode) of [NodeController](../reference/apis-arkui/js-apis-arkui-nodeController.md).
50e41f4b71Sopenharmony_ci
51e41f4b71Sopenharmony_ci```ts
52e41f4b71Sopenharmony_ciimport { BuilderNode, FrameNode, NodeController, UIContext } from '@kit.ArkUI'
53e41f4b71Sopenharmony_ci
54e41f4b71Sopenharmony_ciclass Params {
55e41f4b71Sopenharmony_ci  text: string = ""
56e41f4b71Sopenharmony_ci
57e41f4b71Sopenharmony_ci  constructor(text: string) {
58e41f4b71Sopenharmony_ci    this.text = text;
59e41f4b71Sopenharmony_ci  }
60e41f4b71Sopenharmony_ci}
61e41f4b71Sopenharmony_ci
62e41f4b71Sopenharmony_ci@Builder
63e41f4b71Sopenharmony_cifunction buildText(params: Params) {
64e41f4b71Sopenharmony_ci  Column() {
65e41f4b71Sopenharmony_ci    Text(params.text)
66e41f4b71Sopenharmony_ci      .fontSize(50)
67e41f4b71Sopenharmony_ci      .fontWeight(FontWeight.Bold)
68e41f4b71Sopenharmony_ci      .margin({ bottom: 36 })
69e41f4b71Sopenharmony_ci  }
70e41f4b71Sopenharmony_ci}
71e41f4b71Sopenharmony_ci
72e41f4b71Sopenharmony_ciclass TextNodeController extends NodeController {
73e41f4b71Sopenharmony_ci  private textNode: BuilderNode<[Params]> | null = null;
74e41f4b71Sopenharmony_ci  private message: string = "DEFAULT";
75e41f4b71Sopenharmony_ci
76e41f4b71Sopenharmony_ci  constructor(message: string) {
77e41f4b71Sopenharmony_ci    super();
78e41f4b71Sopenharmony_ci    this.message = message;
79e41f4b71Sopenharmony_ci  }
80e41f4b71Sopenharmony_ci
81e41f4b71Sopenharmony_ci  makeNode(context: UIContext): FrameNode | null {
82e41f4b71Sopenharmony_ci    this.textNode = new BuilderNode(context);
83e41f4b71Sopenharmony_ci    this.textNode.build(wrapBuilder<[Params]>(buildText), new Params(this.message))
84e41f4b71Sopenharmony_ci    return this.textNode.getFrameNode();
85e41f4b71Sopenharmony_ci  }
86e41f4b71Sopenharmony_ci}
87e41f4b71Sopenharmony_ci
88e41f4b71Sopenharmony_ci@Entry
89e41f4b71Sopenharmony_ci@Component
90e41f4b71Sopenharmony_cistruct Index {
91e41f4b71Sopenharmony_ci  @State message: string = "hello"
92e41f4b71Sopenharmony_ci
93e41f4b71Sopenharmony_ci  build() {
94e41f4b71Sopenharmony_ci    Row() {
95e41f4b71Sopenharmony_ci      Column() {
96e41f4b71Sopenharmony_ci        NodeContainer(new TextNodeController(this.message))
97e41f4b71Sopenharmony_ci          .width('100%')
98e41f4b71Sopenharmony_ci          .height(100)
99e41f4b71Sopenharmony_ci          .backgroundColor('#FFF0F0F0')
100e41f4b71Sopenharmony_ci      }
101e41f4b71Sopenharmony_ci      .width('100%')
102e41f4b71Sopenharmony_ci      .height('100%')
103e41f4b71Sopenharmony_ci    }
104e41f4b71Sopenharmony_ci    .height('100%')
105e41f4b71Sopenharmony_ci  }
106e41f4b71Sopenharmony_ci}
107e41f4b71Sopenharmony_ci```
108e41f4b71Sopenharmony_ci
109e41f4b71Sopenharmony_ciWhen combining a BuilderNode with a RenderNode, note the following:
110e41f4b71Sopenharmony_ci
111e41f4b71Sopenharmony_ciIf you mount the RenderNode from the BuilderNode under another RenderNode, you must explicitly specify [selfIdeaSize](../reference/apis-arkui/js-apis-arkui-builderNode.md#renderoptions) as the layout constraint for the BuilderNode. This approach to mounting nodes is not recommended.
112e41f4b71Sopenharmony_ci
113e41f4b71Sopenharmony_ci```ts
114e41f4b71Sopenharmony_ciimport { NodeController, BuilderNode, FrameNode, UIContext, RenderNode } from "@kit.ArkUI"
115e41f4b71Sopenharmony_ci
116e41f4b71Sopenharmony_ciclass Params {
117e41f4b71Sopenharmony_ci  text: string = ""
118e41f4b71Sopenharmony_ci
119e41f4b71Sopenharmony_ci  constructor(text: string) {
120e41f4b71Sopenharmony_ci    this.text = text;
121e41f4b71Sopenharmony_ci  }
122e41f4b71Sopenharmony_ci}
123e41f4b71Sopenharmony_ci
124e41f4b71Sopenharmony_ci@Builder
125e41f4b71Sopenharmony_cifunction buildText(params: Params) {
126e41f4b71Sopenharmony_ci  Column() {
127e41f4b71Sopenharmony_ci    Text(params.text)
128e41f4b71Sopenharmony_ci      .fontSize(50)
129e41f4b71Sopenharmony_ci      .fontWeight(FontWeight.Bold)
130e41f4b71Sopenharmony_ci      .margin({ bottom: 36 })
131e41f4b71Sopenharmony_ci  }
132e41f4b71Sopenharmony_ci}
133e41f4b71Sopenharmony_ci
134e41f4b71Sopenharmony_ciclass TextNodeController extends NodeController {
135e41f4b71Sopenharmony_ci  private rootNode: FrameNode | null = null;
136e41f4b71Sopenharmony_ci  private textNode: BuilderNode<[Params]> | null = null;
137e41f4b71Sopenharmony_ci  private message: string = "DEFAULT";
138e41f4b71Sopenharmony_ci
139e41f4b71Sopenharmony_ci  constructor(message: string) {
140e41f4b71Sopenharmony_ci    super();
141e41f4b71Sopenharmony_ci    this.message = message;
142e41f4b71Sopenharmony_ci  }
143e41f4b71Sopenharmony_ci
144e41f4b71Sopenharmony_ci  makeNode(context: UIContext): FrameNode | null {
145e41f4b71Sopenharmony_ci    this.rootNode = new FrameNode(context);
146e41f4b71Sopenharmony_ci    let renderNode = new RenderNode();
147e41f4b71Sopenharmony_ci    renderNode.clipToFrame = false;
148e41f4b71Sopenharmony_ci    this.textNode = new BuilderNode(context, { selfIdealSize: { width: 150, height: 150 } });
149e41f4b71Sopenharmony_ci    this.textNode.build(wrapBuilder<[Params]>(buildText), new Params(this.message));
150e41f4b71Sopenharmony_ci    const textRenderNode = this.textNode?.getFrameNode()?.getRenderNode();
151e41f4b71Sopenharmony_ci
152e41f4b71Sopenharmony_ci    const rootRenderNode = this.rootNode.getRenderNode();
153e41f4b71Sopenharmony_ci    if (rootRenderNode !== null) {
154e41f4b71Sopenharmony_ci      rootRenderNode.appendChild(renderNode);
155e41f4b71Sopenharmony_ci      renderNode.appendChild(textRenderNode);
156e41f4b71Sopenharmony_ci    }
157e41f4b71Sopenharmony_ci
158e41f4b71Sopenharmony_ci    return this.rootNode;
159e41f4b71Sopenharmony_ci  }
160e41f4b71Sopenharmony_ci}
161e41f4b71Sopenharmony_ci
162e41f4b71Sopenharmony_ci@Entry
163e41f4b71Sopenharmony_ci@Component
164e41f4b71Sopenharmony_cistruct Index {
165e41f4b71Sopenharmony_ci  @State message: string = "hello"
166e41f4b71Sopenharmony_ci
167e41f4b71Sopenharmony_ci  build() {
168e41f4b71Sopenharmony_ci    Row() {
169e41f4b71Sopenharmony_ci      Column() {
170e41f4b71Sopenharmony_ci        NodeContainer(new TextNodeController(this.message))
171e41f4b71Sopenharmony_ci          .width('100%')
172e41f4b71Sopenharmony_ci          .height(100)
173e41f4b71Sopenharmony_ci          .backgroundColor('#FFF0F0F0')
174e41f4b71Sopenharmony_ci      }
175e41f4b71Sopenharmony_ci      .width('100%')
176e41f4b71Sopenharmony_ci      .height('100%')
177e41f4b71Sopenharmony_ci    }
178e41f4b71Sopenharmony_ci    .height('100%')
179e41f4b71Sopenharmony_ci  }
180e41f4b71Sopenharmony_ci}
181e41f4b71Sopenharmony_ci```
182e41f4b71Sopenharmony_ci
183e41f4b71Sopenharmony_ci## Updating the Built-in Component Tree
184e41f4b71Sopenharmony_ci
185e41f4b71Sopenharmony_ciCreate a built-in component tree using the **build** API of a **BuilderNode** object. The tree is constructed based on the **WrappedBuilder** object passed in, and the root node of the component tree is retained.
186e41f4b71Sopenharmony_ci
187e41f4b71Sopenharmony_ciCustom component updates follow the update mechanisms of [state management](../quick-start/arkts-state-management-overview.md). For custom components used directly in a **WrappedBuilder** object, their parent component is the **BuilderNode** object. Therefore, to update child components defined in the **WrappedBuilder** objects, you need to define the relevant state variables with the [@Prop](../quick-start/arkts-prop.md) or [@ObjectLink](../quick-start/arkts-observed-and-objectlink.md) decorator, in accordance with the specifications of state management and the needs of your application development.
188e41f4b71Sopenharmony_ci
189e41f4b71Sopenharmony_ciTo update nodes within a BuilderNode:
190e41f4b71Sopenharmony_ci
191e41f4b71Sopenharmony_ci- Use the **update** API to update individual nodes within the BuilderNode.
192e41f4b71Sopenharmony_ci- Use the [updateConfiguration](../reference/apis-arkui/js-apis-arkui-builderNode.md#updateconfiguration12) API to trigger a full update of all nodes within the BuilderNode.
193e41f4b71Sopenharmony_ci
194e41f4b71Sopenharmony_ci 
195e41f4b71Sopenharmony_ci
196e41f4b71Sopenharmony_ci```ts
197e41f4b71Sopenharmony_ciimport { NodeController, BuilderNode, FrameNode, UIContext } from "@kit.ArkUI"
198e41f4b71Sopenharmony_ci
199e41f4b71Sopenharmony_ciclass Params {
200e41f4b71Sopenharmony_ci  text: string = ""
201e41f4b71Sopenharmony_ci  constructor(text: string) {
202e41f4b71Sopenharmony_ci    this.text = text;
203e41f4b71Sopenharmony_ci  }
204e41f4b71Sopenharmony_ci}
205e41f4b71Sopenharmony_ci
206e41f4b71Sopenharmony_ci// Custom component
207e41f4b71Sopenharmony_ci@Component
208e41f4b71Sopenharmony_cistruct TextBuilder {
209e41f4b71Sopenharmony_ci  // The @Prop decorated attribute is the attribute to be updated in the custom component. It is a basic attribute.
210e41f4b71Sopenharmony_ci  @Prop message: string = "TextBuilder";
211e41f4b71Sopenharmony_ci
212e41f4b71Sopenharmony_ci  build() {
213e41f4b71Sopenharmony_ci    Row() {
214e41f4b71Sopenharmony_ci      Column() {
215e41f4b71Sopenharmony_ci        Text(this.message)
216e41f4b71Sopenharmony_ci          .fontSize(50)
217e41f4b71Sopenharmony_ci          .fontWeight(FontWeight.Bold)
218e41f4b71Sopenharmony_ci          .margin({ bottom: 36 })
219e41f4b71Sopenharmony_ci          .backgroundColor(Color.Gray)
220e41f4b71Sopenharmony_ci      }
221e41f4b71Sopenharmony_ci    }
222e41f4b71Sopenharmony_ci  }
223e41f4b71Sopenharmony_ci}
224e41f4b71Sopenharmony_ci
225e41f4b71Sopenharmony_ci@Builder
226e41f4b71Sopenharmony_cifunction buildText(params: Params) {
227e41f4b71Sopenharmony_ci  Column() {
228e41f4b71Sopenharmony_ci    Text(params.text)
229e41f4b71Sopenharmony_ci      .fontSize(50)
230e41f4b71Sopenharmony_ci      .fontWeight(FontWeight.Bold)
231e41f4b71Sopenharmony_ci      .margin({ bottom: 36 })
232e41f4b71Sopenharmony_ci    TextBuilder({ message: params.text }) // Custom component
233e41f4b71Sopenharmony_ci  }
234e41f4b71Sopenharmony_ci}
235e41f4b71Sopenharmony_ci
236e41f4b71Sopenharmony_ciclass TextNodeController extends NodeController {
237e41f4b71Sopenharmony_ci  private textNode: BuilderNode<[Params]> | null = null;
238e41f4b71Sopenharmony_ci  private message: string = "";
239e41f4b71Sopenharmony_ci
240e41f4b71Sopenharmony_ci  constructor(message: string) {
241e41f4b71Sopenharmony_ci    super()
242e41f4b71Sopenharmony_ci    this.message = message
243e41f4b71Sopenharmony_ci  }
244e41f4b71Sopenharmony_ci
245e41f4b71Sopenharmony_ci  makeNode(context: UIContext): FrameNode | null {
246e41f4b71Sopenharmony_ci    this.textNode = new BuilderNode(context);
247e41f4b71Sopenharmony_ci    this.textNode.build(wrapBuilder<[Params]>(buildText), new Params(this.message))
248e41f4b71Sopenharmony_ci    return this.textNode.getFrameNode();
249e41f4b71Sopenharmony_ci  }
250e41f4b71Sopenharmony_ci
251e41f4b71Sopenharmony_ci  update(message: string) {
252e41f4b71Sopenharmony_ci    if (this.textNode !== null) {
253e41f4b71Sopenharmony_ci      // Call update to perform an update.
254e41f4b71Sopenharmony_ci      this.textNode.update(new Params(message));
255e41f4b71Sopenharmony_ci    }
256e41f4b71Sopenharmony_ci  }
257e41f4b71Sopenharmony_ci}
258e41f4b71Sopenharmony_ci
259e41f4b71Sopenharmony_ci@Entry
260e41f4b71Sopenharmony_ci@Component
261e41f4b71Sopenharmony_cistruct Index {
262e41f4b71Sopenharmony_ci  @State message: string = "hello"
263e41f4b71Sopenharmony_ci  private textNodeController: TextNodeController = new TextNodeController(this.message);
264e41f4b71Sopenharmony_ci  private count = 0;
265e41f4b71Sopenharmony_ci
266e41f4b71Sopenharmony_ci  build() {
267e41f4b71Sopenharmony_ci    Row() {
268e41f4b71Sopenharmony_ci      Column() {
269e41f4b71Sopenharmony_ci        NodeContainer(this.textNodeController)
270e41f4b71Sopenharmony_ci          .width('100%')
271e41f4b71Sopenharmony_ci          .height(200)
272e41f4b71Sopenharmony_ci          .backgroundColor('#FFF0F0F0')
273e41f4b71Sopenharmony_ci        Button('Update')
274e41f4b71Sopenharmony_ci          .onClick(() => {
275e41f4b71Sopenharmony_ci            this.count += 1;
276e41f4b71Sopenharmony_ci            const message = "Update " + this.count.toString();
277e41f4b71Sopenharmony_ci            this.textNodeController.update(message);
278e41f4b71Sopenharmony_ci          })
279e41f4b71Sopenharmony_ci      }
280e41f4b71Sopenharmony_ci      .width('100%')
281e41f4b71Sopenharmony_ci      .height('100%')
282e41f4b71Sopenharmony_ci    }
283e41f4b71Sopenharmony_ci    .height('100%')
284e41f4b71Sopenharmony_ci  }
285e41f4b71Sopenharmony_ci}
286e41f4b71Sopenharmony_ci```
287e41f4b71Sopenharmony_ci
288e41f4b71Sopenharmony_ci## Canceling the Reference to the Entity Node
289e41f4b71Sopenharmony_ci
290e41f4b71Sopenharmony_ciA **BuilderNode** object is mapped to a backend entity node, and its memory release is usually contingent on the disposal of the frontend object. To directly release the backend node object, you can call the [dispose](../reference/apis-arkui/js-apis-arkui-builderNode.md#dispose12) API to break the reference to the entity node. Once this is done, the frontend **BuilderNode** object will no longer affect the lifecycle of the entity node.
291e41f4b71Sopenharmony_ci
292e41f4b71Sopenharmony_ci> **NOTE**
293e41f4b71Sopenharmony_ci>
294e41f4b71Sopenharmony_ci> Calling **dispose** on a **BuilderNode** object breaks its reference to the backend entity node, and also simultaneously severs the references of its contained FrameNode and RenderNode to their respective entity nodes.
295e41f4b71Sopenharmony_ci
296e41f4b71Sopenharmony_ci## Injecting a Touch Event
297e41f4b71Sopenharmony_ci
298e41f4b71Sopenharmony_ciUse the [postTouchEvent](../reference/apis-arkui/js-apis-arkui-builderNode.md#posttouchevent) API in the BuilderNode to inject a [touch event](../reference/apis-arkui/arkui-ts/ts-universal-events-touch.md) into the bound component for event simulation and forwarding. 
299e41f4b71Sopenharmony_ci
300e41f4b71Sopenharmony_ciThe following example forwards a touch event from one **Column** component to another in the BuilderNode, so that when the lower **Column** component is touched, the upper **Column** component also receives the same touch event. The API returns **true** if the button's event is successfully recognized.
301e41f4b71Sopenharmony_ci
302e41f4b71Sopenharmony_ci```ts
303e41f4b71Sopenharmony_ciimport { NodeController, BuilderNode, FrameNode, UIContext } from '@kit.ArkUI';
304e41f4b71Sopenharmony_ci
305e41f4b71Sopenharmony_ciclass Params {
306e41f4b71Sopenharmony_ci  text: string = "this is a text"
307e41f4b71Sopenharmony_ci}
308e41f4b71Sopenharmony_ci
309e41f4b71Sopenharmony_ci@Builder
310e41f4b71Sopenharmony_cifunction ButtonBuilder(params: Params) {
311e41f4b71Sopenharmony_ci  Column() {
312e41f4b71Sopenharmony_ci    Button(`button ` + params.text)
313e41f4b71Sopenharmony_ci      .borderWidth(2)
314e41f4b71Sopenharmony_ci      .backgroundColor(Color.Orange)
315e41f4b71Sopenharmony_ci      .width("100%")
316e41f4b71Sopenharmony_ci      .height("100%")
317e41f4b71Sopenharmony_ci      .gesture(
318e41f4b71Sopenharmony_ci        TapGesture()
319e41f4b71Sopenharmony_ci          .onAction((event: GestureEvent) => {
320e41f4b71Sopenharmony_ci            console.log("TapGesture");
321e41f4b71Sopenharmony_ci          })
322e41f4b71Sopenharmony_ci      )
323e41f4b71Sopenharmony_ci  }
324e41f4b71Sopenharmony_ci  .width(500)
325e41f4b71Sopenharmony_ci  .height(300)
326e41f4b71Sopenharmony_ci  .backgroundColor(Color.Gray)
327e41f4b71Sopenharmony_ci}
328e41f4b71Sopenharmony_ci
329e41f4b71Sopenharmony_ciclass MyNodeController extends NodeController {
330e41f4b71Sopenharmony_ci  private rootNode: BuilderNode<[Params]> | null = null;
331e41f4b71Sopenharmony_ci  private wrapBuilder: WrappedBuilder<[Params]> = wrapBuilder(ButtonBuilder);
332e41f4b71Sopenharmony_ci
333e41f4b71Sopenharmony_ci  makeNode(uiContext: UIContext): FrameNode | null {
334e41f4b71Sopenharmony_ci    this.rootNode = new BuilderNode(uiContext);
335e41f4b71Sopenharmony_ci    this.rootNode.build(this.wrapBuilder, { text: "this is a string" })
336e41f4b71Sopenharmony_ci    return this.rootNode.getFrameNode();
337e41f4b71Sopenharmony_ci  }
338e41f4b71Sopenharmony_ci
339e41f4b71Sopenharmony_ci  postTouchEvent(touchEvent: TouchEvent): void {
340e41f4b71Sopenharmony_ci    if (this.rootNode == null) {
341e41f4b71Sopenharmony_ci      return;
342e41f4b71Sopenharmony_ci    }
343e41f4b71Sopenharmony_ci    let result = this.rootNode.postTouchEvent(touchEvent);
344e41f4b71Sopenharmony_ci    console.log("result " + result);
345e41f4b71Sopenharmony_ci  }
346e41f4b71Sopenharmony_ci}
347e41f4b71Sopenharmony_ci
348e41f4b71Sopenharmony_ci@Entry
349e41f4b71Sopenharmony_ci@Component
350e41f4b71Sopenharmony_cistruct MyComponent {
351e41f4b71Sopenharmony_ci  private nodeController: MyNodeController = new MyNodeController();
352e41f4b71Sopenharmony_ci
353e41f4b71Sopenharmony_ci  build() {
354e41f4b71Sopenharmony_ci    Column() {
355e41f4b71Sopenharmony_ci      NodeContainer(this.nodeController)
356e41f4b71Sopenharmony_ci        .height(300)
357e41f4b71Sopenharmony_ci        .width(500)
358e41f4b71Sopenharmony_ci      Column()
359e41f4b71Sopenharmony_ci        .width(500)
360e41f4b71Sopenharmony_ci        .height(300)
361e41f4b71Sopenharmony_ci        .backgroundColor(Color.Pink)
362e41f4b71Sopenharmony_ci        .onTouch((event) => {
363e41f4b71Sopenharmony_ci          if (event != undefined) {
364e41f4b71Sopenharmony_ci            this.nodeController.postTouchEvent(event);
365e41f4b71Sopenharmony_ci          }
366e41f4b71Sopenharmony_ci        })
367e41f4b71Sopenharmony_ci    }
368e41f4b71Sopenharmony_ci  }
369e41f4b71Sopenharmony_ci}
370e41f4b71Sopenharmony_ci```
371e41f4b71Sopenharmony_ci<!--no_check-->