• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# BuilderNode
2
3The **BuilderNode** module provides APIs for creating a BuilderNode – a custom node that can be used to mount native components. A BuilderNode can be used only as a leaf node. Whenever possible, avoid operating child nodes and their attributes under the root node through the root node's render node.
4
5> **NOTE**
6>
7> The initial APIs of this module are supported since API version 11. Newly added APIs will be marked with a superscript to indicate their earliest API version.
8>
9> **BuilderNode** is not available in DevEco Studio Previewer.
10
11## Modules to Import
12
13```ts
14import { BuilderNode, RenderOptions, NodeRenderType } from "@ohos.arkui.node";
15```
16
17## NodeRenderType
18
19Enumerates the node rendering types.
20
21**System capability**: SystemCapability.ArkUI.ArkUI.Full
22
23| Name               | Value | Description                        |
24| ------------------- | --- | ---------------------------- |
25| RENDER_TYPE_DISPLAY | 0   | The node is displayed on the screen.|
26| RENDER_TYPE_TEXTURE | 1   | The node is exported as a texture.  |
27
28## RenderOptions
29
30Provides optional parameters for creating a BuilderNode.
31
32**System capability**: SystemCapability.ArkUI.ArkUI.Full
33
34| Name         | Type                                  | Mandatory| Description                                                        |
35| ------------- | -------------------------------------- | ---- | ------------------------------------------------------------ |
36| selfIdealSize | [Size](js-apis-arkui-graphics.md#size) | No  | Ideal size of the node.                                            |
37| type          | [NodeRenderType](#noderendertype)      | No  | Rendering type of the node.                                            |
38| surfaceId     | string                                 | No  | Surface ID of the texture receiver. Generally, the texture receiver is an [OH_NativeImage](../native-apis/_o_h___native_image.md#oh_nativeimage) instance.|
39
40## BuilderNode
41
42class BuilderNode<Args extends Object[]>
43
44Implements a BuilderNode, which can create a component tree through the stateless UI method [@Builder](../../quick-start/arkts-builder.md) and hold the root node of the component tree. A BuilderNode cannot be defined as a state variable. The FrameNode held in the BuilderNode is only used to mount the BuilderNode to other FrameNodes as a child node. Undefined behavior may occur if you set attributes or perform operations on subnodes of the FrameNode held by the BuilderNode. Therefore, after you have obtained a [RenderNode](js-apis-arkui-renderNode.md#rendernode) through the [getFrameNode](#getframenode) method of the BuilderNode and the [getRenderNode](js-apis-arkui-frameNode.md#getrendernode) method of the [FrameNode](js-apis-arkui-frameNode.md#framenode), avoid setting the attributes or operating the subnodes through APIs of the [RenderNode](js-apis-arkui-renderNode.md#rendernode).
45
46**System capability**: SystemCapability.ArkUI.ArkUI.Full
47
48### constructor
49
50constructor(uiContext: UIContext, options?: RenderOptions)
51
52Constructor for creating a BuilderNode. When the content generated by the BuilderNode is embedded in another RenderNode for display, that is, the RenderNode corresponding to the BuilderNode is mounted to another RenderNode for display, **selfIdealSize** in **RenderOptions** must be explicitly specified. If **selfIdealSize** is not set, the node in the builder follows the default parent component layout constraint [0, 0], which means that the size of the root node of the subtree in BuilderNode is [0, 0].
53
54**System capability**: SystemCapability.ArkUI.ArkUI.Full
55
56| Name   | Type                                   | Mandatory| Description                                                             |
57| --------- | --------------------------------------- | ---- | ----------------------------------------------------------------- |
58| uiContext | [UIContext](js-apis-arkui-UIContext.md) | Yes  | UI context. For details about how to obtain it, see [[Obtaining UI Context](./js-apis-arkui-node.md#obtaining-ui-context).|
59| options   | [RenderOptions](#renderoptions)         | No  | Parameters for creating a BuilderNode.                                      |
60
61### build
62
63build(builder: WrappedBuilder\<Args>, arg?: Object): void
64
65Creates a component tree based on the passed object and holds the root node of the component tree. The stateless UI method [@Builder](../../quick-start/arkts-builder.md) has at most one root node.
66Custom components are allowed. Yet, the custom components cannot use decorators, such as [@Reusable](../../quick-start/arkts-create-custom-components.md#basic-usage-of-custom-components), [@Link](../../quick-start/arkts-link.md), [@Prop](../../quick-start/arkts-prop.md), [@Provide](../../quick-start/arkts-provide-and-consume.md), and [@Consume](../../quick-start/arkts-provide-and-consume.md), for state synchronization with the owning page.
67
68**System capability**: SystemCapability.ArkUI.ArkUI.Full
69
70**Parameters**
71
72| Name | Type                                                           | Mandatory| Description                                                                                  |
73| ------- | --------------------------------------------------------------- | ---- | -------------------------------------------------------------------------------------- |
74| builder | [WrappedBuilder\<Args>](../../quick-start/arkts-wrapBuilder.md) | Yes  | Stateless UI method [@Builder](../../quick-start/arkts-builder.md) required for creating a component tree.|
75| arg     | Object                                                          | No  | Object, which is used as the input parameter of the builder.                                                         |
76
77
78### getFrameNode
79
80getFrameNode(): FrameNode | null
81
82Obtains the FrameNode in the BuilderNode. The FrameNode is generated only after the BuilderNode executes the build operation.
83
84**System capability**: SystemCapability.ArkUI.ArkUI.Full
85
86**Return value**
87
88| Type                                                     | Description                                                                 |
89| --------------------------------------------------------- | --------------------------------------------------------------------- |
90| [FrameNode](js-apis-arkui-frameNode.md#framenode) \| null | **FrameNode** object. If no such object is held by the **BuilderNode** instance, null is returned.|
91
92**Example 1**
93
94In this example, the BuilderNode is returned as the root node of the **\<NodeContainer>**.
95
96```ts
97import { NodeController, BuilderNode, FrameNode } from "@ohos.arkui.node"
98import { UIContext } from '@ohos.arkui.UIContext';
99
100class Params {
101  text: string = ""
102  constructor(text: string) {
103    this.text = text;
104  }
105}
106
107@Builder
108function buildText(params: Params) {
109  Column() {
110    Text(params.text)
111      .fontSize(50)
112      .fontWeight(FontWeight.Bold)
113      .margin({bottom: 36})
114  }
115}
116
117class TextNodeController extends NodeController {
118  private textNode: BuilderNode<[Params]> | null = null;
119  private message: string = "DEFAULT";
120
121  constructor(message: string) {
122    super();
123    this.message = message;
124  }
125
126  makeNode(context: UIContext): FrameNode | null {
127    this.textNode = new BuilderNode(context);
128    this.textNode.build(wrapBuilder<[Params]>(buildText), new Params(this.message))
129
130    return this.textNode.getFrameNode();
131  }
132}
133
134@Entry
135@Component
136struct Index {
137  @State message: string = "hello"
138
139  build() {
140    Row() {
141      Column() {
142        NodeContainer(new TextNodeController(this.message))
143          .width('100%')
144          .height(100)
145          .backgroundColor('#FFF0F0F0')
146      }
147      .width('100%')
148      .height('100%')
149    }
150    .height('100%')
151  }
152}
153```
154
155**Example 2**
156
157This example mounts the RenderNode of the BuilderNode to another RenderNode.
158
159```ts
160import { NodeController, BuilderNode, FrameNode } from "@ohos.arkui.node"
161import { UIContext } from '@ohos.arkui.UIContext';
162
163class Params {
164  text: string = ""
165
166  constructor(text: string) {
167    this.text = text;
168  }
169}
170
171@Builder
172function buildText(params: Params) {
173  Column() {
174    Text(params.text)
175      .fontSize(50)
176      .fontWeight(FontWeight.Bold)
177      .margin({ bottom: 36 })
178  }
179}
180
181class TextNodeController extends NodeController {
182  private rootNode: FrameNode | null = null;
183  private textNode: BuilderNode<[Params]> | null = null;
184  private message: string = "DEFAULT";
185
186  constructor(message: string) {
187    super();
188    this.message = message;
189  }
190
191  makeNode(context: UIContext): FrameNode | null {
192    this.rootNode = new FrameNode(context);
193
194    this.textNode = new BuilderNode(context, { selfIdealSize: { width: 150, height: 150 } });
195    this.textNode.build(wrapBuilder<[Params]>(buildText), new Params(this.message));
196    const textRenderNode = this.textNode?.getFrameNode()?.getRenderNode();
197
198    const rootRenderNode = this.rootNode.getRenderNode();
199    if (rootRenderNode !== null) {
200      rootRenderNode.appendChild(textRenderNode);
201    }
202
203    return this.rootNode;
204  }
205}
206
207@Entry
208@Component
209struct Index {
210  @State message: string = "hello"
211
212  build() {
213    Row() {
214      Column() {
215        NodeContainer(new TextNodeController(this.message))
216          .width('100%')
217          .height(100)
218          .backgroundColor('#FFF0F0F0')
219      }
220      .width('100%')
221      .height('100%')
222    }
223    .height('100%')
224  }
225}
226```
227
228### update
229
230update(arg: Object): void
231
232Updates this BuilderNode based on the provided parameter, which is of the same type as the input parameter passed to the [build](###build) API. To call this API on a custom component, the variable used in the component must be defined as the @Prop type.
233
234**System capability**: SystemCapability.ArkUI.ArkUI.Full
235
236**Parameters**
237
238| Name| Type  | Mandatory| Description                                                                    |
239| ------ | ------ | ---- | ------------------------------------------------------------------------ |
240| arg    | Object | Yes  | Parameter used to update the BuilderNode. It is of the same type as the parameter passed to the [build](###build) API.|
241
242**Example**
243```ts
244import { UIContext } from '@ohos.arkui.UIContext';
245import { NodeController, BuilderNode, FrameNode } from "@ohos.arkui.node"
246
247class Params {
248  text: string = ""
249  constructor(text: string) {
250    this.text = text;
251  }
252}
253
254// Custom component
255@Component
256struct TextBuilder {
257  @Prop message: string = "TextBuilder";
258
259  build() {
260    Row() {
261      Column() {
262        Text(this.message)
263          .fontSize(50)
264          .fontWeight(FontWeight.Bold)
265          .margin({bottom: 36})
266          .backgroundColor(Color.Gray)
267      }
268    }
269  }
270}
271
272@Builder
273function buildText(params: Params) {
274  Column() {
275    Text(params.text)
276      .fontSize(50)
277      .fontWeight(FontWeight.Bold)
278      .margin({ bottom: 36 })
279    TextBuilder({message: params.text}) //Custom component
280  }
281}
282
283class TextNodeController extends NodeController {
284  private rootNode: FrameNode | null = null;
285  private textNode: BuilderNode<[Params]> | null = null;
286  private message: string = "";
287
288  constructor(message: string) {
289    super()
290    this.message = message
291  }
292
293  makeNode(context: UIContext): FrameNode | null {
294    this.textNode = new BuilderNode(context);
295    this.textNode.build(wrapBuilder<[Params]>(buildText), new Params(this.message))
296    return this.textNode.getFrameNode();
297  }
298
299  update(message: string) {
300    if (this.textNode !== null) {
301      this.textNode.update(new Params(message));
302    }
303  }
304}
305
306@Entry
307@Component
308struct Index {
309  @State message: string = "hello"
310  private textNodeController: TextNodeController = new TextNodeController(this.message);
311  private count = 0;
312
313  build() {
314    Row() {
315      Column() {
316        NodeContainer(this.textNodeController)
317          .width('100%')
318          .height(100)
319          .backgroundColor('#FFF0F0F0')
320        Button('Update')
321          .onClick(() => {
322            this.count += 1;
323            const message = "Update " + this.count.toString();
324            this.textNodeController.update(message);
325          })
326      }
327      .width('100%')
328      .height('100%')
329    }
330    .height('100%')
331  }
332}
333```
334
335### postTouchEvent
336
337postTouchEvent(event: TouchEvent): boolean
338
339Dispatches an event to the FrameNode created by this BuilderNode.
340
341**System capability**: SystemCapability.ArkUI.ArkUI.Full
342
343**Parameters**
344
345| Name| Type                                                                     | Mandatory| Description      |
346| ------ | ------------------------------------------------------------------------- | ---- | ---------- |
347| event  | [TouchEvent](../arkui-ts/ts-universal-events-touch.md#touchevent) | Yes  | Touch event.|
348
349**Return value**
350
351| Type   | Description              |
352| ------- | ------------------ |
353| boolean | Whether the event is successfully dispatched.|
354
355**Example**
356
357```ts
358import { UIContext } from '@ohos.arkui.UIContext';
359import { NodeController, BuilderNode, FrameNode } from '@ohos.arkui.node';
360
361class Params {
362  text: string = "this is a text"
363}
364
365@Builder
366function ButtonBuilder(params: Params) {
367  Column() {
368    Button(`button ` + params.text)
369      .borderWidth(2)
370      .backgroundColor(Color.Orange)
371      .width("100%")
372      .height("100%")
373      .gesture(
374        TapGesture()
375          .onAction((event: GestureEvent) => {
376            console.log("TapGesture");
377          })
378      )
379  }
380  .width(500)
381  .height(300)
382  .backgroundColor(Color.Gray)
383}
384
385class MyNodeController extends NodeController {
386  private rootNode: BuilderNode<[Params]> | null = null;
387  private wrapBuilder: WrappedBuilder<[Params]> = wrapBuilder(ButtonBuilder);
388
389  makeNode(uiContext: UIContext): FrameNode | null {
390    this.rootNode = new BuilderNode(uiContext);
391    this.rootNode.build(this.wrapBuilder, { text: "this is a string" })
392    return this.rootNode.getFrameNode();
393  }
394
395  postTouchEvent(touchEvent: TouchEvent): void {
396    if(this.rootNode == null){
397      return;
398    }
399    let result = this.rootNode.postTouchEvent(touchEvent);
400    console.log("result " + result);
401  }
402}
403
404@Entry
405@Component
406struct MyComponent {
407  private nodeController: MyNodeController = new MyNodeController();
408
409  build() {
410    Column() {
411      NodeContainer(this.nodeController)
412        .height(300)
413        .width(500)
414
415      Column()
416        .width(500)
417        .height(300)
418        .backgroundColor(Color.Pink)
419        .onTouch((event) => {
420          if(event != undefined){
421            this.nodeController.postTouchEvent(event);
422          }
423        })
424    }
425  }
426}
427```
428