• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# ComponentContent
2
3**ComponentContent** represents an entity encapsulation of component content, which can be created and transmitted outside of UI components. It allows you to encapsulate and decouple dialog box components. The underlying implementation of **ComponentContent** uses BuilderNode. For details, see [BuilderNode](js-apis-arkui-builderNode.md).
4
5> **NOTE**
6>
7> The initial APIs of this module are supported since API version 12. Newly added APIs will be marked with a superscript to indicate their earliest API version.
8>
9> **ComponentContent** is not available in DevEco Studio Previewer.
10
11
12## Modules to Import
13
14```ts
15import { ComponentContent } from '@kit.ArkUI';
16```
17
18## ComponentContent
19
20### constructor
21
22constructor(uiContext: UIContext, builder: WrappedBuilder\<[]>)
23
24A constructor used to create a **ComponentContent** object.
25
26**Atomic service API**: This API can be used in atomic services since API version 12.
27
28**System capability**: SystemCapability.ArkUI.ArkUI.Full
29
30**Parameters**
31
32| Name   | Type                                     | Mandatory| Description                              |
33| --------- | ----------------------------------------- | ---- | ---------------------------------- |
34| uiContext | [UIContext](./js-apis-arkui-UIContext.md) | Yes  | UI context required for creating the node.|
35| builder  | [WrappedBuilder\<[]>](../../ui/state-management/arkts-wrapBuilder.md) | Yes  |   **WrappedBuilder** object that encapsulates a builder function that has no parameters.|
36
37### constructor
38
39constructor(uiContext: UIContext, builder: WrappedBuilder\<[T]>, args: T)
40
41A constructor used to create a **ComponentContent** object.
42
43**Atomic service API**: This API can be used in atomic services since API version 12.
44
45**System capability**: SystemCapability.ArkUI.ArkUI.Full
46
47**Parameters**
48
49| Name   | Type                                     | Mandatory| Description                              |
50| --------- | ----------------------------------------- | ---- | ---------------------------------- |
51| uiContext | [UIContext](./js-apis-arkui-UIContext.md) | Yes  | UI context required for creating the node.|
52| builder  | [WrappedBuilder\<[T]>](../../ui/state-management/arkts-wrapBuilder.md) | Yes  |   **WrappedBuilder** object that encapsulates a builder function that has parameters.|
53| args     |     T     |   Yes  |   Parameters of the builder function encapsulated in the **WrappedBuilder** object.|
54
55### constructor
56
57  constructor(uiContext: UIContext, builder: WrappedBuilder\<[T]>, args: T, options: BuildOptions)
58
59A constructor used to create a **ComponentContent** object.
60
61**Atomic service API**: This API can be used in atomic services since API version 12.
62
63**System capability**: SystemCapability.ArkUI.ArkUI.Full
64
65**Parameters**
66
67| Name   | Type                                     | Mandatory| Description                              |
68| --------- | ----------------------------------------- | ---- | ---------------------------------- |
69| uiContext | [UIContext](./js-apis-arkui-UIContext.md) | Yes  | UI context required for creating the node.|
70| builder  | [WrappedBuilder\<[T]>](../../ui/state-management/arkts-wrapBuilder.md) | Yes  |   **WrappedBuilder** object that encapsulates a builder function that has parameters.|
71| args     |     T     |   Yes  |   Parameters of the builder function encapsulated in the **WrappedBuilder** object.|
72| options | [BuildOptions](./js-apis-arkui-builderNode.md#buildoptions12)                                                    | Yes  |  Build options, which determine whether to support the behavior of nesting **@Builder** within **@Builder**.                                        |
73
74**Example**
75``` ts
76import { ComponentContent, NodeContent, typeNode } from "@kit.ArkUI"
77
78interface ParamsInterface {
79  text: string;
80  func: Function;
81}
82
83@Builder
84function buildTextWithFunc(fun: Function) {
85  Text(fun())
86    .fontSize(50)
87    .fontWeight(FontWeight.Bold)
88    .margin({ bottom: 36 })
89}
90
91@Builder
92function buildText(params: ParamsInterface) {
93  Column() {
94    Text(params.text)
95      .fontSize(50)
96      .fontWeight(FontWeight.Bold)
97      .margin({ bottom: 36 })
98    buildTextWithFunc(params.func)
99  }
100}
101
102@Entry
103@Component
104struct Index {
105  @State message: string = "HELLO"
106  private content: NodeContent = new NodeContent();
107
108  build() {
109    Row() {
110      Column() {
111        Button('addComponentContent')
112          .onClick(() => {
113            let column = typeNode.createNode(this.getUIContext(), "Column");
114            column.initialize();
115            column.addComponentContent(new ComponentContent<ParamsInterface>(this.getUIContext(),
116              wrapBuilder<[ParamsInterface]>(buildText), {
117                text: this.message, func: () => {
118                  return "FUNCTION"
119                }
120              }, { nestingBuilderSupported: true }))
121            this.content.addFrameNode(column);
122          })
123        ContentSlot(this.content)
124      }
125      .id("column")
126      .width('100%')
127      .height('100%')
128    }
129    .height('100%')
130  }
131}
132
133```
134
135### update
136
137update(args: T): void
138
139Updates the parameters of the builder function encapsulated in the **WrappedBuilder** object. The parameter type must be the same as that passed in **constructor**.
140
141**Atomic service API**: This API can be used in atomic services since API version 12.
142
143**System capability**: SystemCapability.ArkUI.ArkUI.Full
144
145**Parameters**
146
147| Name| Type| Mandatory| Description                                                        |
148| ------ | ---- | ---- | ------------------------------------------------------------ |
149| args   | T    | Yes  | Parameters of the builder function encapsulated in the **WrappedBuilder** object. The parameter type must be the same as that passed in **constructor**.|
150
151**Example**
152
153```ts
154import { ComponentContent } from "@kit.ArkUI";
155
156class Params {
157  text: string = ""
158  constructor(text: string) {
159    this.text = text;
160  }
161}
162
163@Builder
164function buildText(params: Params) {
165  Column() {
166    Text(params.text)
167      .fontSize(50)
168      .fontWeight(FontWeight.Bold)
169      .margin({bottom: 36})
170  }.backgroundColor('#FFF0F0F0')
171}
172
173@Entry
174@Component
175struct Index {
176  @State message: string = "hello"
177
178  build() {
179    Row() {
180      Column() {
181        Button("click me")
182            .onClick(() => {
183                let uiContext = this.getUIContext();
184                let promptAction = uiContext.getPromptAction();
185                let contentNode = new ComponentContent(uiContext, wrapBuilder(buildText), new Params(this.message));
186                promptAction.openCustomDialog(contentNode);
187
188                setTimeout(() => {
189                  contentNode.update(new Params("new message"));
190                }, 2000);    // Automatically update the text in the dialog box after 2 seconds.
191            })
192      }
193      .width('100%')
194      .height('100%')
195    }
196    .height('100%')
197  }
198}
199```
200
201### reuse
202
203reuse(param?: Object): void
204
205Passes the reuse event to the custom component in this **ComponentContent** object.
206
207**Atomic service API**: This API can be used in atomic services since API version 12.
208
209**System capability**: SystemCapability.ArkUI.ArkUI.Full
210
211**Parameters**
212
213| Name| Type  | Mandatory| Description                                                                    |
214| ------ | ------ | ---- | ------------------------------------------------------------------------ |
215| param  | Object | No  | Parameters of the builder function encapsulated in the **WrappedBuilder** object. The parameter type must be the same as that passed in **constructor**.|
216
217### recycle
218
219recycle(): void
220
221Passes the recycle event to the custom component in this **ComponentContent** object.
222
223**Atomic service API**: This API can be used in atomic services since API version 12.
224
225**System capability**: SystemCapability.ArkUI.ArkUI.Full
226
227```ts
228import { NodeContent, typeNode, ComponentContent } from "@kit.ArkUI";
229
230const TEST_TAG: string = "Reuse+Recycle";
231
232class MyDataSource {
233  private dataArray: string[] = [];
234  private listener: DataChangeListener | null = null
235
236  public totalCount(): number {
237    return this.dataArray.length;
238  }
239
240  public getData(index: number) {
241    return this.dataArray[index];
242  }
243
244  public pushData(data: string) {
245    this.dataArray.push(data);
246  }
247
248  public reloadListener(): void {
249    this.listener?.onDataReloaded();
250  }
251
252  public registerDataChangeListener(listener: DataChangeListener): void {
253    this.listener = listener;
254  }
255
256  public unregisterDataChangeListener(): void {
257    this.listener = null;
258  }
259}
260
261class Params {
262  item: string = '';
263
264  constructor(item: string) {
265    this.item = item;
266  }
267}
268
269@Builder
270function buildNode(param: Params = new Params("hello")) {
271  Row() {
272    Text(`C${param.item} -- `)
273    ReusableChildComponent2({ item: param.item }) // This custom component cannot be correctly reused in the ComponentContent.
274  }
275}
276
277// The custom component that is reused and recycled will have its state variables updated, and the state variables of the nested custom component ReusableChildComponent3 will also be updated. However, the ComponentContent will block this propagation process.
278@Reusable
279@Component
280struct ReusableChildComponent {
281  @Prop item: string = '';
282  @Prop switch: string = '';
283  private content: NodeContent = new NodeContent();
284  private componentContent: ComponentContent<Params> = new ComponentContent<Params>(
285    this.getUIContext(),
286    wrapBuilder<[Params]>(buildNode),
287    new Params(this.item),
288    { nestingBuilderSupported: true });
289
290  aboutToAppear() {
291    let column = typeNode.createNode(this.getUIContext(), "Column");
292    column.initialize();
293    column.addComponentContent(this.componentContent);
294    this.content.addFrameNode(column);
295  }
296
297  aboutToRecycle(): void {
298    console.log(`${TEST_TAG} ReusableChildComponent aboutToRecycle ${this.item}`);
299
300    // When the switch is open, pass the recycle event to the nested custom component, such as ReusableChildComponent2, through the ComponentContent's recycle API to complete recycling.
301    if (this.switch === 'open') {
302      this.componentContent.recycle();
303    }
304  }
305
306  aboutToReuse(params: object): void {
307    console.log(`${TEST_TAG} ReusableChildComponent aboutToReuse ${JSON.stringify(params)}`);
308
309    // When the switch is open, pass the reuse event to the nested custom component, such as ReusableChildComponent2, through the ComponentContent's reuse API to complete reuse.
310    if (this.switch === 'open') {
311      this.componentContent.reuse(params);
312    }
313  }
314
315  build() {
316    Row() {
317      Text(`A${this.item}--`)
318      ReusableChildComponent3({ item: this.item })
319      ContentSlot(this.content)
320    }
321  }
322}
323
324@Component
325struct ReusableChildComponent2 {
326  @Prop item: string = "false";
327
328  aboutToReuse(params: Record<string, object>) {
329    console.log(`${TEST_TAG} ReusableChildComponent2 aboutToReuse ${JSON.stringify(params)}`);
330  }
331
332  aboutToRecycle(): void {
333    console.log(`${TEST_TAG} ReusableChildComponent2 aboutToRecycle ${this.item}`);
334  }
335
336  build() {
337    Row() {
338      Text(`D${this.item}`)
339        .fontSize(20)
340        .backgroundColor(Color.Yellow)
341        .margin({ left: 10 })
342    }.margin({ left: 10, right: 10 })
343  }
344}
345
346@Component
347struct ReusableChildComponent3 {
348  @Prop item: string = "false";
349
350  aboutToReuse(params: Record<string, object>) {
351    console.log(`${TEST_TAG} ReusableChildComponent3 aboutToReuse ${JSON.stringify(params)}`);
352  }
353
354  aboutToRecycle(): void {
355    console.log(`${TEST_TAG} ReusableChildComponent3 aboutToRecycle ${this.item}`);
356  }
357
358  build() {
359    Row() {
360      Text(`B${this.item}`)
361        .fontSize(20)
362        .backgroundColor(Color.Yellow)
363        .margin({ left: 10 })
364    }.margin({ left: 10, right: 10 })
365  }
366}
367
368
369@Entry
370@Component
371struct Index {
372  @State data: MyDataSource = new MyDataSource();
373
374  aboutToAppear() {
375    for (let i = 0; i < 100; i++) {
376      this.data.pushData(i.toString());
377    }
378  }
379
380  build() {
381    Column() {
382      List({ space: 3 }) {
383        LazyForEach(this.data, (item: string) => {
384          ListItem() {
385            ReusableChildComponent({
386              item: item,
387              switch: 'open' // Changing open to close can be used to observe the behavior of custom components inside the ComponentContent when reuse and recycle events are not passed through the ComponentContent's reuse and recycle APIs.
388            })
389          }
390        }, (item: string) => item)
391      }
392      .width('100%')
393      .height('100%')
394    }
395  }
396}
397```
398
399### dispose
400
401dispose(): void
402
403Disposes of this **ComponentContent** object, which means to cancel the reference relationship between the **ComponentContent** object and its backend entity node.
404
405**Atomic service API**: This API can be used in atomic services since API version 12.
406
407**System capability**: SystemCapability.ArkUI.ArkUI.Full
408
409**Example**
410
411```ts
412import { BusinessError } from '@kit.BasicServicesKit';
413import { ComponentContent } from '@kit.ArkUI';
414
415class Params {
416  text: string = ""
417  constructor(text: string) {
418    this.text = text;
419  }
420}
421
422@Builder
423function buildText(params: Params) {
424  Column() {
425    Text(params.text)
426      .fontSize(50)
427      .fontWeight(FontWeight.Bold)
428      .margin({bottom: 36})
429  }.backgroundColor('#FFF0F0F0')
430}
431
432@Entry
433@Component
434struct Index {
435  @State message: string = "hello"
436
437  build() {
438    Row() {
439      Column() {
440        Button("click me")
441            .onClick(() => {
442                let uiContext = this.getUIContext();
443                let promptAction = uiContext.getPromptAction();
444                let contentNode = new ComponentContent(uiContext, wrapBuilder(buildText), new Params(this.message));
445                promptAction.openCustomDialog(contentNode);
446
447                setTimeout(() => {
448                  promptAction.closeCustomDialog(contentNode)
449                    .then(() => {
450                      console.info('customdialog closed.')
451                      if (contentNode !== null) {
452                        contentNode.dispose();   // Dispose of the contentNode object.
453                      }
454                    }).catch((error: BusinessError) => {
455                      let message = (error as BusinessError).message;
456                      let code = (error as BusinessError).code;
457                      console.error(`closeCustomDialog args error code is ${code}, message is ${message}`);
458                    })
459                }, 2000);     // Automatically close the dialog box after 2 seconds.
460            })
461      }
462      .width('100%')
463      .height('100%')
464    }
465    .height('100%')
466  }
467}
468```
469
470
471### updateConfiguration
472
473updateConfiguration(): void
474
475Updates the configuration of the entire node by passing in a [system environment change](../apis-ability-kit/js-apis-app-ability-configuration.md) event.
476
477**Atomic service API**: This API can be used in atomic services since API version 12.
478
479**System capability**: SystemCapability.ArkUI.ArkUI.Full
480
481> **NOTE**
482>
483> The **updateConfiguration** API is used to instruct an object to update itself. The update is based on the current changes in the system environment.
484
485**Example**
486```ts
487import { NodeController, FrameNode, ComponentContent } from '@kit.ArkUI';
488import { AbilityConstant, Configuration, EnvironmentCallback, ConfigurationConstant } from '@kit.AbilityKit';
489
490@Builder
491function buildText() {
492  Column() {
493    Text('Hello')
494      .fontSize(36)
495      .fontWeight(FontWeight.Bold)
496  }
497  .backgroundColor($r('sys.color.ohos_id_color_background'))
498  .width('100%')
499  .alignItems(HorizontalAlign.Center)
500  .padding(16)
501}
502
503const componentContentMap: Array<ComponentContent<[Object]>> = new Array();
504
505class MyNodeController extends NodeController {
506  private rootNode: FrameNode | null = null;
507
508  makeNode(uiContext: UIContext): FrameNode | null {
509    return this.rootNode;
510  }
511
512  createNode(context: UIContext) {
513    this.rootNode = new FrameNode(context);
514    let component = new ComponentContent<Object>(context, wrapBuilder(buildText));
515    componentContentMap.push(component);
516    this.rootNode.addComponentContent(component);
517  }
518
519  deleteNode() {
520    let node = componentContentMap.pop();
521    this.rootNode?.dispose();
522    node?.dispose();
523  }
524}
525
526function updateColorMode() {
527  componentContentMap.forEach((value, index) => {
528    value.updateConfiguration();
529  })
530}
531
532@Entry
533@Component
534struct FrameNodeTypeTest {
535  private myNodeController: MyNodeController = new MyNodeController();
536
537  aboutToAppear(): void {
538    let environmentCallback: EnvironmentCallback = {
539      onMemoryLevel: (level: AbilityConstant.MemoryLevel): void => {
540        console.log('onMemoryLevel');
541      },
542      onConfigurationUpdated: (config: Configuration): void => {
543        console.log('onConfigurationUpdated ' + JSON.stringify(config));
544        updateColorMode();
545      }
546    }
547    // Register a callback.
548    this.getUIContext().getHostContext()?.getApplicationContext().on('environment', environmentCallback);
549    // Set the application color mode to follow the system settings.
550    this.getUIContext()
551      .getHostContext()?.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET);
552    this.myNodeController.createNode(this.getUIContext());
553  }
554
555  aboutToDisappear(): void {
556    // Remove the reference to the custom node from the map and release the node.
557    this.myNodeController.deleteNode();
558  }
559
560  build() {
561    Column({ space: 16 }) {
562      NodeContainer(this.myNodeController);
563      Button('Switch to Dark Mode')
564        .onClick(() => {
565          this.getUIContext()
566            .getHostContext()?.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_DARK);
567        })
568      Button('Switch to Light Mode')
569        .onClick(() => {
570          this.getUIContext()
571            .getHostContext()?.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT);
572        })
573    }
574  }
575}
576```
577