• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Popup Control
2
3You can bind a popup to a component, specifying its content, interaction logic, and display status.
4
5>  **NOTE**
6>
7>  This attribute is supported since API version 7. Updates will be marked with a superscript to indicate their earliest API version.
8
9
10## APIs
11
12
13| Name       | Type                                    | Description                                      |
14| --------- | ---------------------------------------- | ---------------------------------------- |
15| bindPopup | show: boolean,<br>popup: [PopupOptions](#popupoptions) \| [CustomPopupOptions](#custompopupoptions8)<sup>8+</sup> | Binds a popup to the component.<br>**show**: whether to show the popup. The default value is **false**, indicating that the popup is hidden. As the popup can be displayed only after building of all pages is completed, **show** cannot be set to **true** during page building. Otherwise, the display position and shape of the popup will be incorrect.<br>**popup**: parameters of the popup.|
16
17## PopupOptions
18
19| Name                                 | Type                                                        | Mandatory| Description                                                        |
20| ------------------------------------- | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ |
21| message                               | string                                                       | Yes  | Content of the popup message.                                              |
22| placementOnTop<sup>(deprecated)</sup> | boolean                                                      | No  | Whether to display the popup above the component.<br/>Default value: **false**<br>**NOTE**<br>This API is deprecated since API version 10. You are advised to use **placement** instead. |
23| primaryButton                         | {<br>value: string,<br>action: () =&gt; void<br>} | No  | Primary button.<br>**value**: text of the primary button in the popup.<br>**action**: callback for clicking the primary button.|
24| secondaryButton                       | {<br>value: string,<br>action: () =&gt; void<br>} | No  | Secondary button.<br>**value**: text of the secondary button in the popup.<br>**action**: callback for clicking the secondary button.|
25| onStateChange                         | (event: { isVisible: boolean }) =&gt; void | No  | Callback for the popup status change event.<br>**isVisible**: whether the popup is visible. |
26| arrowOffset<sup>9+</sup>              | [Length](ts-types.md#length)                                 | No  | Offset of the popup arrow relative to the popup.<br>When the arrow is at the top or bottom of the popup: The value **0** indicates that the arrow is located on the leftmost, and any other value indicates the distance from the arrow to the leftmost; the arrow is centered by default.<br/>When the arrow is on the left or right side of the popup: The value indicates the distance from the arrow to the top; the arrow is centered by default.<br/>When the popup is displayed on either edge of the screen, it will automatically deviate leftward or rightward to stay within the safe area. When the value is **0**, the arrow always points to the bound component. |
27| showInSubWindow<sup>9+</sup>          | boolean                                                      | No  | Whether to show the popup in the subwindow.<br/>Default value: **false**                  |
28| mask<sup>10+</sup>                    | boolean \| [ResourceColor](ts-types.md#resourcecolor) | No  | Whether to apply a mask to the popup. The value **true** means to apply a transparent mask to the popup, **false** means not to apply a mask to the popup, and a color value means to apply a mask in the corresponding color to the popup.|
29| messageOptions<sup>10+</sup>          | [PopupMessageOptions](#popupmessageoptions10)                | No  | Parameters of the popup message.                                      |
30| targetSpace<sup>10+</sup>             | [Length](ts-types.md#length)                                 | No  | Space between the popup and the target.                                     |
31| placement<sup>10+</sup>               | [Placement](ts-appendix-enums.md#placement8)                 | No  | Position of the popup relative to the target. The default value is **Placement.Bottom**.<br>If both **placementOnTop** and **placement** are set, the latter prevails.|
32| offset<sup>10+</sup>                  | [Position](ts-types.md#position8)                            | No  | Offset of the popup relative to the display position specified by **placement**.<br>**NOTE**<br>This parameter cannot be set in percentage.|
33| enableArrow<sup>10+</sup>             | boolean                                                      | No  | Whether to display the arrow.<br>Default value: **true**|
34
35## PopupMessageOptions<sup>10+</sup>
36
37| Name       | Type                                      | Mandatory  | Description         |
38| --------- | ---------------------------------------- | ---- | ----------- |
39| textColor | [ResourceColor](ts-types.md#resourcecolor) | No   | Text color of the popup message.|
40| font      | [Font](ts-types.md#Font)                 | No   | Font attributes of the popup message.|
41## CustomPopupOptions<sup>8+</sup>
42
43| Name                          | Type                                      | Mandatory  | Description                                      |
44| ---------------------------- | ---------------------------------------- | ---- | ---------------------------------------- |
45| builder                      | [CustomBuilder](ts-types.md#custombuilder8) | Yes   | Popup builder.<br>**NOTE**<br>The **popup** attribute is a universal attribute. A custom popup does not support display of another popup. The **position** attribute cannot be used for the first-layer container under the builder. If the **position** attribute is used, the popup will not be displayed.                             |
46| placement                    | [Placement](ts-appendix-enums.md#placement8) | No   | Preferred position of the popup. If the set position is insufficient for holding the popup, it will be automatically adjusted.<br>Default value: **Placement.Bottom**|
47| popupColor                   | [ResourceColor](ts-types.md#resourcecolor) | No   | Color of the popup.<br>Default value: **'#4d4d4d'**|
48| enableArrow                  | boolean                                  | No   | Whether to display an arrow.<br>Since API version 9, if the position set for the popup is not large enough, the arrow will not be displayed. For example, if **placement** is set to **Left**, but the popup height (80 vp) is less than the sum of the arrow width (32 vp) and diameter of popup rounded corner (48 vp), the arrow will not be displayed.<br>Default value: **true**|
49| autoCancel                   | boolean                                  | No   | Whether to automatically close the popup when an operation is performed on the page.<br>Default value: **true**           |
50| onStateChange                | (event: { isVisible: boolean }) =&gt; void | No   | Callback for the popup status change event.<br/>**isVisible**: whether the popup is visible.           |
51| arrowOffset<sup>9+</sup>     | [Length](ts-types.md#length)             | No   | Offset of the popup arrow relative to the popup.<br/>When the arrow is at the top or bottom of the popup: The value **0** indicates that the arrow is located on the leftmost, and any other value indicates the distance from the arrow to the leftmost; the arrow is centered by default.<br/>When the arrow is on the left or right side of the popup: The value indicates the distance from the arrow to the top; the arrow is centered by default.<br/>When the popup is displayed on either edge of the screen, it will automatically deviate leftward or rightward to stay within the safe area. When the value is **0**, the arrow always points to the bound component. |
52| showInSubWindow<sup>9+</sup> | boolean                                  | No   | Whether to show the popup in the subwindow. The default value is **false**.                   |
53| maskColor<sup>(deprecated)</sup> | [ResourceColor](ts-types.md#resourcecolor)   | No  | Color of the popup mask.<br>**NOTE**<br>This parameter is deprecated since API version 10. You are advised to use **mask** instead.|
54| mask<sup>10+</sup>           | boolean \| [ResourceColor](ts-types.md#resourcecolor) | No   | Whether to apply a mask to the popup. The value **true** means to apply a transparent mask to the popup, **false** means not to apply a mask to the popup, and a color value means to apply a mask in the corresponding color to the popup.|
55| targetSpace<sup>10+</sup>    | [Length](ts-types.md#length)             | No   | Space between the popup and the target.                          |
56| offset<sup>10+</sup>         | [Position](ts-types.md#position8)                            | No  | Offset of the popup relative to the display position specified by **placement**.<br>**NOTE**<br>This parameter cannot be set in percentage.|
57
58## Example
59
60### Example 1
61
62```ts
63// xxx.ets
64@Entry
65@Component
66struct PopupExample {
67  @State handlePopup: boolean = false
68  @State customPopup: boolean = false
69
70  // Popup builder
71  @Builder popupBuilder() {
72    Row({ space: 2 }) {
73      Image($r("app.media.image")).width(24).height(24).margin({ left: -5 })
74      Text('Custom Popup').fontSize(10)
75    }.width(100).height(50).padding(5)
76  }
77
78  build() {
79    Flex({ direction: FlexDirection.Column }) {
80      // PopupOptions for setting the popup
81      Button('PopupOptions')
82        .onClick(() => {
83          this.handlePopup = !this.handlePopup
84        })
85        .bindPopup(this.handlePopup, {
86          message: 'This is a popup with PopupOptions',
87          placementOnTop: true,
88          showInSubWindow:false,
89          primaryButton: {
90            value: 'confirm',
91            action: () => {
92              this.handlePopup = !this.handlePopup
93              console.info('confirm Button click')
94            }
95          },
96          // Secondary button
97          secondaryButton: {
98            value: 'cancel',
99            action: () => {
100              this.handlePopup = !this.handlePopup
101              console.info('cancel Button click')
102            }
103          },
104          onStateChange: (e) => {
105            console.info(JSON.stringify(e.isVisible))
106            if (!e.isVisible) {
107              this.handlePopup = false
108            }
109          }
110        })
111        .position({ x: 100, y: 50 })
112
113
114      // CustomPopupOptions for setting the popup
115      Button('CustomPopupOptions')
116        .onClick(() => {
117          this.customPopup = !this.customPopup
118        })
119        .bindPopup(this.customPopup, {
120          builder: this.popupBuilder,
121          placement: Placement.Top,
122          mask: {color:'0x33000000'},
123          popupColor: Color.Yellow,
124          enableArrow: true,
125          showInSubWindow: false,
126          onStateChange: (e) => {
127            if (!e.isVisible) {
128              this.customPopup = false
129            }
130          }
131        })
132        .position({ x: 80, y: 200 })
133    }.width('100%').padding({ top: 5 })
134  }
135}
136```
137
138![figures/popup.gif](figures/popup.gif)
139
140### Example 2
141
142```ts
143// xxx.ets
144@Entry
145@Component
146struct PopupExample {
147  @State handlePopup: boolean = false
148
149  build() {
150    Column() {
151      Button('PopupOptions')
152        .onClick(() => {
153          this.handlePopup = !this.handlePopup
154        })
155        .bindPopup(this.handlePopup, {
156          message: 'This is a popup with PopupOptions',
157          messageOptions: {
158            textColor: Color.Red,
159            font: {
160              size: '14vp',
161              style: FontStyle.Italic,
162              weight: FontWeight.Bolder
163            }
164          },
165          placement: Placement.Bottom,
166          enableArrow: false,
167          targetSpace: '15vp',
168          onStateChange: (e) => {
169            console.info(JSON.stringify(e.isVisible))
170            if (!e.isVisible) {
171              this.handlePopup = false
172            }
173          }
174        })
175    }.margin(20)
176  }
177}
178```
179
180![](figures/popup_2.png)
181
182### Example 3
183
184```ts
185// xxx.ets
186@Entry
187@Component
188struct PopupExample {
189  @State customPopup: boolean = false
190
191  // Popup builder
192  @Builder popupBuilder() {
193    Row() {
194      Text('Custom Popup Message').fontSize(10)
195    }.height(50).padding(5)
196  }
197
198  build() {
199    Column() {
200      // CustomPopupOptions for setting the popup
201      Button('CustomPopupOptions')
202        .onClick(() => {
203          this.customPopup = !this.customPopup
204        })
205        .bindPopup(this.customPopup, {
206          builder: this.popupBuilder,
207          targetSpace: '15vp',
208          enableArrow: false,
209          onStateChange: (e) => {
210            if (!e.isVisible) {
211              this.customPopup = false
212            }
213          }
214        })
215    }.margin(20)
216  }
217}
218```
219
220![](figures/popup_3.png)
221