1# NodeController 2 3The **NodeController** module provides APIs for managing custom nodes, such as creating, showing, and updating custom nodes, and APIs for mounting custom nodes to a [NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md#nodecontainer) component. 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> **NodeController** is not available in DevEco Studio Previewer. 10 11## Modules to Import 12 13```ts 14import { NodeController } from '@kit.ArkUI'; 15``` 16 17## NodeController 18 19Implements a **NodeController** instance to manage the bound [NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md#nodecontainer) component. One **NodeController** instance can be bound to only one [NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md#nodecontainer) component. 20 21**Atomic service API**: This API can be used in atomic services since API version 12. 22 23**System capability**: SystemCapability.ArkUI.ArkUI.Full 24 25### makeNode 26 27abstract makeNode(uiContext : UIContext): FrameNode | null 28 29Called when the [NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md#nodecontainer) component bound to this **NodeController** instance is created. This callback returns a node, which will be mounted to the **NodeContainer**. 30This callback can also be invoked through the **rebuild()** method of **NodeController**. 31 32**Atomic service API**: This API can be used in atomic services since API version 12. 33 34**System capability**: SystemCapability.ArkUI.ArkUI.Full 35 36**Parameters** 37 38| Name | Type | Mandatory| Description | 39| --------- | ----------------------------------------- | ---- | ------------------------------------------------------------------------------------------------------------- | 40| uiContext | [UIContext](./js-apis-arkui-UIContext.md) | Yes | UI context of the bound **NodeContainer** component.| 41 42**Return value** 43 44| Type | Description | 45| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 46| [FrameNode](./js-apis-arkui-frameNode.md#framenode)\| null | **FrameNode** object, which will be mounted to the placeholder node of the **NodeContainer** component. If a **null** object is returned, the child nodes of the corresponding **NodeContainer** component are removed.| 47 48### aboutToAppear 49 50aboutToAppear?(): void 51 52Called after the [NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md#nodecontainer) component bound to this **NodeController** instance is attached and about to appear. 53 54> **NOTE** 55> 56> For details about the callback timing, see [onAppear](arkui-ts/ts-universal-events-show-hide.md#onappear). 57 58**Atomic service API**: This API can be used in atomic services since API version 12. 59 60**System capability**: SystemCapability.ArkUI.ArkUI.Full 61 62### aboutToDisappear 63 64aboutToDisappear?(): void 65 66Called when the [NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md#nodecontainer) component bound to this **NodeController** instance is detached and about to be hidden. 67 68> **NOTE** 69> 70> For details about the callback timing, see [onDisAppear](arkui-ts/ts-universal-events-show-hide.md#ondisappear). 71 72**Atomic service API**: This API can be used in atomic services since API version 12. 73 74**System capability**: SystemCapability.ArkUI.ArkUI.Full 75 76### onAttach<sup>18+</sup> 77 78onAttach?(): void 79 80Called when the [NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md#nodecontainer) component bound to this **NodeController** instance is attached to the main node tree. 81 82> **NOTE** 83> 84> For details about the callback timing, see [onAttach](arkui-ts/ts-universal-events-show-hide.md#onattach12). 85 86**Atomic service API**: This API can be used in atomic services since API version 18. 87 88**System capability**: SystemCapability.ArkUI.ArkUI.Full 89 90### onDetach<sup>18+</sup> 91 92onDetach?(): void 93 94Called when the [NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md#nodecontainer) component bound to this **NodeController** instance is detached from the main node tree. 95 96> **NOTE** 97> 98> For details about the callback timing, see [onDetach](arkui-ts/ts-universal-events-show-hide.md#ondetach12). 99 100**Atomic service API**: This API can be used in atomic services since API version 18. 101 102**System capability**: SystemCapability.ArkUI.ArkUI.Full 103 104### onWillBind<sup>18+</sup> 105 106onWillBind?(containerId: number): void 107 108Called when this **NodeController** instance is about to be bound to a [NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md#nodecontainer) component. 109 110**Atomic service API**: This API can be used in atomic services since API version 18. 111 112**System capability**: SystemCapability.ArkUI.ArkUI.Full 113 114**Parameters** 115 116| Name | Type | Mandatory| Description | 117| ----------- | ------ |----- |---------------------------------------------------------------------------------------------------------------------------------- | 118| containerId | number | Yes | ID of the [NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md#nodecontainer) component to which the **NodeController** instance is about to be bound.| 119 120### onWillUnbind<sup>18+</sup> 121 122onWillUnbind?(containerId: number): void 123 124Called when this **NodeController** instance is about to be unbound from a [NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md#nodecontainer) component. 125 126**Atomic service API**: This API can be used in atomic services since API version 18. 127 128**System capability**: SystemCapability.ArkUI.ArkUI.Full 129 130**Parameters** 131 132| Name | Type | Mandatory| Description | 133| ----------- | ------ |----- |---------------------------------------------------------------------------------------------------------------------------------- | 134| containerId | number | Yes | ID of the [NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md#nodecontainer) component from which the **NodeController** instance is about to be unbound.| 135 136### onBind<sup>18+</sup> 137 138onBind?(containerId: number): void 139 140Called after this **NodeController** instance is bound to a [NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md#nodecontainer) component. 141 142**Atomic service API**: This API can be used in atomic services since API version 18. 143 144**System capability**: SystemCapability.ArkUI.ArkUI.Full 145 146**Parameters** 147 148| Name | Type | Mandatory| Description | 149| ----------- | ------ |----- |---------------------------------------------------------------------------------------------------------------------------------- | 150| containerId | number | Yes | ID of the [NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md#nodecontainer) component to which the **NodeController** instance is bound.| 151 152### onUnbind<sup>18+</sup> 153 154onUnbind?(containerId: number): void 155 156Called after this **NodeController** instance is unbound from a [NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md#nodecontainer) component. 157 158**Atomic service API**: This API can be used in atomic services since API version 18. 159 160**System capability**: SystemCapability.ArkUI.ArkUI.Full 161 162**Parameters** 163 164| Name | Type | Mandatory| Description | 165| ----------- | ------ |----- |---------------------------------------------------------------------------------------------------------------------------------- | 166| containerId | number | Yes | ID of the [NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md#nodecontainer) component from which the **NodeController** instance is unbound.| 167 168### aboutToResize 169 170aboutToResize?(size: Size): void 171 172Called when the [NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md#nodecontainer) component bound to this **NodeController** instance is resized. 173 174**Atomic service API**: This API can be used in atomic services since API version 12. 175 176**System capability**: SystemCapability.ArkUI.ArkUI.Full 177 178**Parameters** 179 180| Name| Type | Mandatory| Description | 181| ------ | ---------------------------------------- | ---- | ---------------------------------------- | 182| size | [Size](./js-apis-arkui-graphics.md#size) | Yes | Width and height of the component, in vp.| 183 184### onTouchEvent 185 186onTouchEvent?(event: TouchEvent): void 187 188Called when the [NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md#nodecontainer) component bound to this **NodeController** instance receives a touch event. 189 190**Atomic service API**: This API can be used in atomic services since API version 12. 191 192**System capability**: SystemCapability.ArkUI.ArkUI.Full 193 194**Parameters** 195 196| Name| Type | Mandatory| Description | 197| ------ | ------------------------------------------------------------------------- | ---- | ---------- | 198| event | [TouchEvent](arkui-ts/ts-universal-events-touch.md#touchevent) | Yes | Touch event.| 199 200### rebuild 201 202rebuild(): void 203 204Instructs the [NodeContainer](arkui-ts/ts-basic-components-nodecontainer.md#nodecontainer) component bound to this **NodeController** instance to call the [makeNode](#makenode) API again to change child nodes. 205 206**Atomic service API**: This API can be used in atomic services since API version 12. 207 208**System capability**: SystemCapability.ArkUI.ArkUI.Full 209 210> **NOTE** 211> Since the **rebuild** API is actively called by the application and is tied to the UI, you need to ensure that the UI context is valid at the time of the call, that is, it must be consistent with the UI context of the bound NodeContainer. 212> 213> In cases where the UI context is unclear, for example, during event callbacks, you can use the [runScopedTask](./js-apis-arkui-UIContext.md#runscopedtask) method of [UIContext](./js-apis-arkui-UIContext.md) to explicitly define the UI context at the time of the call. 214 215## Example 216 217### Example 1: Implementing Lifecycle Callbacks for Node Layout, Touch, Mounting, and Unmounting Events 218 219This example demonstrates how to manage the lifecycle of a **NodeContainer** component using **aboutToResize**, **onTouchEvent**, 220 221**aboutToAppear**, and **aboutToDisappear**. 222 223It also shows how to mount a BuilderNode using **NodeController**. 224 225```ts 226import { NodeController, BuilderNode, Size, FrameNode ,UIContext } from '@kit.ArkUI'; 227 228class Params { 229 text: string = "this is a text" 230} 231 232@Builder 233function buttonBuilder(params: Params) { 234 Column() { 235 Button(params.text) 236 .fontSize(12) 237 .borderRadius(8) 238 .borderWidth(2) 239 .backgroundColor(Color.Orange) 240 } 241} 242 243class MyNodeController extends NodeController { 244 private buttonNode: BuilderNode<[Params]> | null = null; 245 private wrapBuilder: WrappedBuilder<[Params]> = wrapBuilder(buttonBuilder); 246 247 makeNode(uiContext: UIContext): FrameNode { 248 if (this.buttonNode == null) { 249 this.buttonNode = new BuilderNode(uiContext); 250 this.buttonNode.build(this.wrapBuilder, { text: "This is a Button" }) 251 } 252 return this.buttonNode!.getFrameNode()!; 253 } 254 255 aboutToResize(size: Size) { 256 console.log("aboutToResize width : " + size.width + " height : " + size.height) 257 } 258 259 aboutToAppear() { 260 console.log("aboutToAppear") 261 } 262 263 aboutToDisappear() { 264 console.log("aboutToDisappear"); 265 } 266 267 onTouchEvent(event:TouchEvent) { 268 console.log("onTouchEvent"); 269 } 270} 271 272@Entry 273@Component 274struct Index { 275 private myNodeController: MyNodeController = new MyNodeController(); 276 277 build() { 278 Column() { 279 NodeContainer(this.myNodeController) 280 } 281 .padding({ left: 35, right: 35, top: 35 }) 282 .width("100%") 283 .height("100%") 284 } 285} 286``` 287 288 289### Example 2: Implementing Lifecycle Callbacks for Node Binding/Unbinding and Tree Attachment/Detachment 290 291This example demonstrates how to manage the lifecycle of a **NodeContainer** component when it is attached to or detached from the main node tree and 292 293when it is bound or unbound, using **onAttach**, **onDetach**, **onWillBind**, **onWillUnbind**, **onBind**, and **onUnbind**. 294 295```ts 296import { NodeController, BuilderNode, Size, FrameNode, UIContext } from '@kit.ArkUI'; 297class Params { 298 text: string = "this is a text" 299} 300 301@Builder 302function buttonBuilder(params: Params) { 303 Column() { 304 Button(params.text) 305 .fontSize(20) 306 .borderRadius(8) 307 .borderWidth(2) 308 .backgroundColor(Color.Grey) 309 } 310} 311 312class MyNodeController extends NodeController { 313 private buttonNode: BuilderNode<[Params]> | null = null; 314 private wrapBuilder: WrappedBuilder<[Params]> = wrapBuilder(buttonBuilder); 315 316 makeNode(uiContext: UIContext): FrameNode { 317 if (this.buttonNode == null) { 318 this.buttonNode = new BuilderNode(uiContext); 319 this.buttonNode.build(this.wrapBuilder, { text: "This is a Button" }) 320 } 321 return this.buttonNode!.getFrameNode()!; 322 } 323 324 onAttach(): void { 325 console.log("myButton on attach"); 326 } 327 328 onDetach(): void { 329 console.log("myButton on detach"); 330 } 331 332 onWillBind(containerId: number): void{ 333 console.log("myButton on WillBind" + containerId); 334 } 335 336 onWillUnbind(containerId: number): void{ 337 console.log("myButton on WillUnbind" + containerId); 338 } 339 340 onBind(containerId: number): void { 341 console.log("myButton on bind: " + containerId); 342 } 343 344 onUnbind(containerId: number): void { 345 console.log("myButton on unbind: " + containerId); 346 } 347} 348 349@Entry 350@Component 351struct Index { 352 @State buttonShow: boolean = true 353 @State buttonIndex: number = 0 354 private buttonController: MyNodeController = new MyNodeController(); 355 private buttonNull: null = null; 356 private buttonControllerArray: Array < MyNodeController | null > = [this.buttonController,this.buttonNull] 357 358 build() { 359 Column() { 360 Row(){ 361 Button("Bind/Unbind") 362 .onClick(() => { 363 this.buttonIndex++; 364 }).margin(5) 365 Button("onAttach/onDetach") 366 .onClick(() => { 367 this.buttonShow = !this.buttonShow 368 }).margin(5) 369 } 370 if(this.buttonShow){ 371 NodeContainer(this.buttonControllerArray[this.buttonIndex % this.buttonControllerArray.length]) 372 } 373 } 374 .padding({ left: 35, right: 35}) 375 .width("100%") 376 .height("100%") 377 } 378} 379``` 380 381 382