• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Global Popups Independent of UI Components (openPopup)
2
3The [Popup](arkts-popup-and-menu-components-popup.md) API is a great option for creating popups, but it relies on a bound UI component to work. Since API version 18, however, the global API [openPopup](../reference/apis-arkui/js-apis-arkui-UIContext.md#openpopup18) offers a more flexible solution. This API can be used directly or encapsulated in scenarios where no bound UI components are available, making it ideal for use cases such as event callbacks or when integrating with external systems.
4
5## Displaying a Popup
6
7To display a popup, call the [openPopup](../reference/apis-arkui/js-apis-arkui-UIContext.md#openpopup18) API. Here's a basic example:
8
9   ```ts
10   promptAction.openPopup(contentNode, { id: targetId }, {
11     enableArrow: true
12   })
13     .then(() => {
14       console.info('openPopup success');
15     })
16     .catch((err: BusinessError) => {
17       console.info('openPopup error: ' + err.code + ' ' + err.message);
18     })
19   ```
20
21### Creating a ComponentContent Instance
22
23   When using **openPopup**, you need to provide a [ComponentContent](../reference/apis-arkui/js-apis-arkui-ComponentContent.md) instance to define the popup content. **wrapBuilder(buildText)** encapsulates the custom component, and **new Params(this.message)** is the input parameter for the custom component. This parameter is optional and can be a basic data type.
24
25   ```ts
26   private contentNode: ComponentContent<Object> = new ComponentContent(uiContext, wrapBuilder(buildText), this.message);
27   ```
28
29   If your **wrapBuilder** includes other components (such as [Popup](../reference/apis-arkui/arkui-ts/ohos-arkui-advanced-Popup.md#popup) or [Chip](../reference/apis-arkui/arkui-ts/ohos-arkui-advanced-Chip.md#chip)), the [ComponentContent](../reference/apis-arkui/js-apis-arkui-ComponentContent.md#componentcontent-1) constructor must include four parameters, and the **options** parameter must be **{ nestingBuilderSupported: true }**.
30
31   ```ts
32   @Builder
33   export function buildText(params: Params) {
34     Popup({
35       // Set the icon for the menu.
36       icon: {
37         image: $r('app.media.app_icon'),
38         width: 32,
39         height: 32,
40         fillColor: Color.White,
41         borderRadius: 10
42       } as PopupIconOptions,
43       // Set the text content.
44       title: {
45         text: `This is a Popup title 1`,
46         fontSize: 20,
47         fontColor: Color.Black,
48         fontWeight: FontWeight.Normal
49       } as PopupTextOptions,
50       // Set the text content.
51       message: {
52         text: `This is a Popup message 1`,
53         fontSize: 15,
54         fontColor: Color.Black
55       } as PopupTextOptions,
56       // Set the buttons.
57       buttons: [{
58         text: 'confirm',
59         action: () => {
60           console.info('confirm button click')
61         },
62         fontSize: 15,
63         fontColor: Color.Black,
64       },
65         {
66           text: 'cancel',
67           action: () => {
68             console.info('cancel button click')
69           },
70           fontSize: 15,
71           fontColor: Color.Black
72         },] as [PopupButtonOptions?, PopupButtonOptions?]
73     })
74   }
75
76   let contentNode: ComponentContent<Object> = new ComponentContent(uiContext, wrapBuilder(buildText), this.message, { nestingBuilderSupported: true });
77   ```
78
79
80### Providing Bound Component Information
81
82   When calling **openMenu**, you must provide the [TargetInfo](../reference/apis-arkui/js-apis-arkui-UIContext.md#targetinfo18) of the bound component. Without a valid target, the popup won't display.
83
84   ```ts
85   let frameNode: FrameNode | null = this.ctx.getFrameNodeByUniqueId(this.getUniqueId());
86   let targetId = frameNode?.getChild(0)?.getUniqueId();
87   ```
88
89### Customizing the Popup Style
90
91   When calling **openPopup**, you can customize the menu style using [PopupCommonOptions](../reference/apis-arkui/arkui-ts/ts-universal-attributes-popup.md#popupcommonoptions18).
92
93   ```ts
94   private options: PopupCommonOptions = { enableArrow: true };
95   ```
96
97## Updating the Popup Style
98
99To update the popup style, use the [updatePopup](../reference/apis-arkui/js-apis-arkui-UIContext.md#updatepopup18) API. You can update the style fully or incrementally. However, certain properties, including **showInSubWindow**, **focusable**, **onStateChange**, **onWillDismiss**, and **transition**, cannot be updated.
100
101   ```ts
102   promptAction.updatePopup(contentNode, {
103     enableArrow: false
104   }, true)
105     .then(() => {
106       console.info('updatePopup success');
107     })
108     .catch((err: BusinessError) => {
109       console.info('updatePopup error: ' + err.code + ' ' + err.message);
110     })
111   ```
112
113## Closing the Popup
114
115To close the popup, call the [closePopup](../reference/apis-arkui/js-apis-arkui-UIContext.md#closepopup18) API.
116
117   ```ts
118   promptAction.closePopup(contentNode)
119     .then(() => {
120       console.info('closePopup success');
121     })
122     .catch((err: BusinessError) => {
123       console.info('closePopup error: ' + err.code + ' ' + err.message);
124     })
125   ```
126
127> **NOTE**
128>
129> The [updatePopup](../reference/apis-arkui/js-apis-arkui-UIContext.md#updatepopup18) and [closePopup](../reference/apis-arkui/js-apis-arkui-UIContext.md#closepopup18) APIs rely on the content to identify the menu. Therefore, you must maintain the content instance throughout the popup's lifecycle.
130
131
132## Using the Global Popup in HAR Packages
133
134You can encapsulate a popup using the [HAR](../quick-start/har-package.md) package to provide display, update, and close capabilities.
135
136```ts
137// library/src/main/ets/components/MainPage.ets
138
139import { BusinessError } from '@kit.BasicServicesKit';
140import { ComponentContent, TargetInfo, PromptAction } from '@kit.ArkUI';
141
142export class PromptActionClass {
143  private promptAction: PromptAction | null = null;
144  private contentNode: ComponentContent<Object> | null = null;
145  private options: PopupCommonOptions | null = null;
146  private target: TargetInfo | null = null;
147  private isPartialUpdate: boolean = false
148
149  public setPromptAction(promptAction: PromptAction) {
150    this.promptAction = promptAction;
151  }
152
153  public setContentNode(node: ComponentContent<Object>) {
154    this.contentNode = node;
155  }
156
157  public setTarget(target: TargetInfo) {
158    this.target = target;
159  }
160
161  public setOptions(options: PopupCommonOptions) {
162    this.options = options;
163  }
164
165  public setIsPartialUpdate(isPartialUpdate: boolean) {
166    this.isPartialUpdate = isPartialUpdate;
167  }
168
169  public openPopup() {
170    if (this.promptAction != null) {
171      this.promptAction.openPopup(this.contentNode, this.target, this.options)
172        .then(() => {
173          console.info('openPopup success');
174        })
175        .catch((err: BusinessError) => {
176          console.info('openPopup error: ' + err.code + ' ' + err.message);
177        })
178    }
179  }
180
181  public closePopup() {
182    if (this.promptAction != null) {
183      this.promptAction.closePopup(this.contentNode)
184        .then(() => {
185          console.info('closePopup success');
186        })
187        .catch((err: BusinessError) => {
188          console.info('closePopup error: ' + err.code + ' ' + err.message);
189        })
190    }
191  }
192
193  public updatePopup(options: PopupCommonOptions) {
194    if (this.promptAction != null) {
195      this.promptAction.updatePopup(this.contentNode, options, this.isPartialUpdate)
196        .then(() => {
197          console.info('updatePopup success');
198        })
199        .catch((err: BusinessError) => {
200          console.info('updatePopup error: ' + err.code + ' ' + err.message);
201        })
202    }
203  }
204}
205```
206
207```ts
208// entry/src/main/ets/pages/Index.ets
209
210import { PromptActionClass } from "library";
211import { ComponentContent, PromptAction } from '@kit.ArkUI';
212
213class Params {
214  text: string = ""
215  promptActionClass: PromptActionClass = new PromptActionClass();
216
217  constructor(text: string, promptActionClass: PromptActionClass) {
218    this.text = text;
219    this.promptActionClass = promptActionClass;
220  }
221}
222
223@Builder
224function buildText(params: Params) {
225  Column() {
226    Text(params.text)
227      .fontSize(20)
228      .margin({ top: 10 })
229    Button('Update')
230      .margin({ top: 10 })
231      .width(100)
232      .onClick(() => {
233        params.promptActionClass.updatePopup({
234          enableArrow: false,
235        })
236      })
237    Button('Close')
238      .margin({ top: 10 })
239      .width(100)
240      .onClick(() => {
241        params.promptActionClass.closePopup()
242      })
243  }.width(130).height(150)
244}
245
246@Entry
247@Component
248struct Index {
249  @State message: string = "hello"
250  private uiContext: UIContext = this.getUIContext();
251  private promptAction: PromptAction = this.uiContext.getPromptAction();
252  private promptActionClass: PromptActionClass = new PromptActionClass();
253  private targetId: number = 0;
254  private contentNode: ComponentContent<Object> =
255    new ComponentContent(this.uiContext, wrapBuilder(buildText), new Params(this.message, this.promptActionClass));
256  private options: PopupCommonOptions = { enableArrow: true };
257
258  build() {
259    Column() {
260      Button("openPopup")
261        .margin({ top: 50, left: 100 })
262        .onClick(() => {
263          let frameNode: FrameNode | null = this.uiContext.getFrameNodeByUniqueId(this.getUniqueId());
264          let targetId = frameNode?.getChild(0)?.getUniqueId();
265          if (targetId == undefined) {
266            this.targetId = 0;
267          } else {
268            this.targetId = targetId;
269          }
270          this.promptActionClass.setPromptAction(this.promptAction);
271          this.promptActionClass.setContentNode(this.contentNode);
272          this.promptActionClass.setOptions(this.options);
273          this.promptActionClass.setIsPartialUpdate(false);
274          this.promptActionClass.setTarget({ id: this.targetId });
275          this.promptActionClass.openPopup();
276        })
277    }
278  }
279}
280```
281
282![image](figures/UIopenPopup.gif)
283