1# Global Custom Dialog Box Independent of UI Components (Recommended)
2
3
4Due to the restrictions of [CustomDialogController](../reference/apis-arkui/arkui-ts/ts-methods-custom-dialog-box.md#customdialogcontroller), which does not support dynamic creation or refresh, for more complex use cases, you are advised to use the [openCustomDialog](../reference/apis-arkui/js-apis-arkui-UIContext.md#opencustomdialog12) API provided by the **PromptAction** object obtained from **UIContext** to implement a custom dialog box.
5
6
7## Opening and Closing a Custom Dialog Box
8
91. Create a **ComponentContent** instance.
10
11   **ComponentContent** is used to define the content of the custom dialog box. **wrapBuilder(buildText)** encapsulates the custom component, and **new Params(this.message)** is the input parameter for the custom component, which can be omitted or passed in with basic data types.
12
13   ```ts
14   private contentNode: ComponentContent<Object> = new ComponentContent(this.ctx, wrapBuilder(buildText), new Params(this.message));
15   ```
16
172. Open the custom dialog box.
18
19   Call **openCustomDialog** to open the custom dialog box, whose **customStyle** is set to **true** by default, meaning that the dialog box is styled entirely based on the **contentNode** settings you provide.
20
21   ```ts
22   this.ctx.getPromptAction().openCustomDialog(this.contentNode, this.options)
23     .then(() => {
24       console.info('OpenCustomDialog complete.')
25     })
26     .catch((error: BusinessError) => {
27       let message = (error as BusinessError).message;
28       let code = (error as BusinessError).code;
29       console.error(`OpenCustomDialog args error code is ${code}, message is ${message}`);
30     })
31   ```
32
333. Close the custom dialog box.
34
35   Call **closeCustomDialog**, which requires the ComponentContent corresponding to the dialog box to be closed. To set a close method within the dialog box, follow the complete sample to encapsulate this functionality into a static method.
36
37   To release the corresponding ComponentContent after the dialog box is closed, call the **dispose** API of the ComponentContent.
38
39   ```ts
40   this.ctx.getPromptAction().closeCustomDialog(this.contentNode)
41     .then(() => {
42       console.info('CloseCustomDialog complete.')
43     })
44     .catch((error: BusinessError) => {
45       let message = (error as BusinessError).message;
46       let code = (error as BusinessError).code;
47       console.error(`CloseCustomDialog args error code is ${code}, message is ${message}`);
48     })
49   ```
50
51## Updating the Content of a Custom Dialog Box
52
53ComponentContent has the same usage constraints as [BuilderNode](../reference/apis-arkui/js-apis-arkui-builderNode.md) and does not support custom components using decorators such as [@Reusable](../quick-start/arkts-create-custom-components.md#basic-structure-of-a-custom-component), [@Link](../quick-start/arkts-link.md), [@Provide](../quick-start/arkts-provide-and-consume.md), and [@Consume](../quick-start/arkts-provide-and-consume.md) to synchronize the state between the page where the dialog box pops up and the custom component in ComponentContent. Therefore, if you need to update the content of the custom component in the dialog box, use the **update** API provided by ComponentContent.
54```ts
55this.contentNode.update(new Params('update'))
56```
57
58## Updating the Attributes of a Custom Dialog Box
59
60You can dynamically update the attributes of the dialog box through **updateCustomDialog**. Currently, the following attributes are supported: **alignment**, **offset**, **autoCancel**, and **maskColor**.
61Note that when attributes are updated, those unset will be restored to their default values. For example, if you initially set **{ alignment: DialogAlignment.Top, offset: { dx: 0, dy: 50 } }** and then update it to **{ alignment: DialogAlignment.Bottom }**, the initially set **offset: { dx: 0, dy: 50 }** will not be retained; the offset will be restored to the default value.
62```ts
63this.ctx.getPromptAction().updateCustomDialog(this.contentNode, options)
64  .then(() => {
65    console.info('UpdateCustomDialog complete.')
66  })
67  .catch((error: BusinessError) => {
68    let message = (error as BusinessError).message;
69    let code = (error as BusinessError).code;
70    console.error(`UpdateCustomDialog args error code is ${code}, message is ${message}`);
71  })
72```
73
74## Sample
75
76```ts
77// PromptActionClass.ts
78import { BusinessError } from '@kit.BasicServicesKit';
79import { ComponentContent, window } from '@kit.ArkUI';
80import { UIContext } from '@ohos.arkui.UIContext';
81
82export class PromptActionClass {
83  static ctx: UIContext;
84  static contentNode: ComponentContent<Object>;
85  static options: Object;
86
87  static setContext(context: UIContext) {
88    this.ctx = context;
89  }
90
91  static setContentNode(node: ComponentContent<Object>) {
92    this.contentNode = node;
93  }
94
95  static setOptions(options: Object) {
96    this.options = options;
97  }
98
99  static openDialog() {
100    if (this.contentNode !== null) {
101      this.ctx.getPromptAction().openCustomDialog(this.contentNode, this.options)
102        .then(() => {
103          console.info('OpenCustomDialog complete.')
104        })
105        .catch((error: BusinessError) => {
106          let message = (error as BusinessError).message;
107          let code = (error as BusinessError).code;
108          console.error(`OpenCustomDialog args error code is ${code}, message is ${message}`);
109        })
110    }
111  }
112
113  static closeDialog() {
114    if (this.contentNode !== null) {
115      this.ctx.getPromptAction().closeCustomDialog(this.contentNode)
116        .then(() => {
117          console.info('CloseCustomDialog complete.')
118        })
119        .catch((error: BusinessError) => {
120          let message = (error as BusinessError).message;
121          let code = (error as BusinessError).code;
122          console.error(`CloseCustomDialog args error code is ${code}, message is ${message}`);
123        })
124    }
125  }
126
127  static updateDialog(options: Object) {
128    if (this.contentNode !== null) {
129      this.ctx.getPromptAction().updateCustomDialog(this.contentNode, options)
130        .then(() => {
131          console.info('UpdateCustomDialog complete.')
132        })
133        .catch((error: BusinessError) => {
134          let message = (error as BusinessError).message;
135          let code = (error as BusinessError).code;
136          console.error(`UpdateCustomDialog args error code is ${code}, message is ${message}`);
137        })
138    }
139  }
140}
141```
142
143```ts
144// Index.ets
145import { ComponentContent } from '@kit.ArkUI';
146import { PromptActionClass } from './PromptActionClass';
147
148class Params {
149  text: string = ""
150
151  constructor(text: string) {
152    this.text = text;
153  }
154}
155
156@Builder
157function buildText(params: Params) {
158  Column() {
159    Text(params.text)
160      .fontSize(50)
161      .fontWeight(FontWeight.Bold)
162      .margin({ bottom: 36 })
163    Button('Close')
164      .onClick(() => {
165        PromptActionClass.closeDialog()
166      })
167  }.backgroundColor('#FFF0F0F0')
168}
169
170@Entry
171@Component
172struct Index {
173  @State message: string = "hello"
174  private ctx: UIContext = this.getUIContext();
175  private contentNode: ComponentContent<Object> =
176    new ComponentContent(this.ctx, wrapBuilder(buildText), new Params(this.message));
177
178  aboutToAppear(): void {
179    PromptActionClass.setContext(this.ctx);
180    PromptActionClass.setContentNode(this.contentNode);
181    PromptActionClass.setOptions({ alignment: DialogAlignment.Top, offset: { dx: 0, dy: 50 } });
182  }
183
184  build() {
185    Row() {
186      Column() {
187        Button("open dialog and update options")
188          .margin({ top: 50 })
189          .onClick(() => {
190            PromptActionClass.openDialog()
191
192            setTimeout(() => {
193              PromptActionClass.updateDialog({
194                alignment: DialogAlignment.Bottom,
195                offset: { dx: 0, dy: -50 }
196              })
197            }, 1500)
198          })
199        Button("open dialog and update content")
200          .margin({ top: 50 })
201          .onClick(() => {
202            PromptActionClass.openDialog()
203
204            setTimeout(() => {
205              this.contentNode.update(new Params('update'))
206            }, 1500)
207          })
208      }
209      .width('100%')
210      .height('100%')
211    }
212    .height('100%')
213  }
214}
215```
216