1# Basic Custom Dialog Box (CustomDialog) (Not Recommended) 2A custom dialog box is a dialog box you customize by using APIs of the **CustomDialogController** class. It can be used for user interactions, showing ads, award announcements, alerts, software update notifications, and more. For details, see [Custom Dialog Box](../reference/apis-arkui/arkui-ts/ts-methods-custom-dialog-box.md). 3 4> **NOTE** 5> 6> In ArkUI, dialog boxes do not close automatically when you switch pages unless you manually call **close**. To enable a dialog box to be dismissed during page navigation, consider using the [navigation page displayed in dialog mode](arkts-navigation-navigation.md#page-display-mode) or [page-level dialog box](arkts-embedded-dialog.md). 7 8You can specify the modality of a dialog box by setting [isModal](../reference/apis-arkui/arkui-ts/ts-methods-custom-dialog-box.md#customdialogcontrolleroptions). A dialog box is modal if **isModal** is set to **true** and non-modal otherwise. 9 10## Creating a Custom Dialog Box 11 121. Use the \@CustomDialog decorator to create a custom dialog box. You can define the content of the dialog box within the decorator. Note that **CustomDialogController** must be defined in @Component. 13 14 ```ts 15 @CustomDialog 16 struct CustomDialogExample { 17 controller: CustomDialogController = new CustomDialogController({ 18 builder: CustomDialogExample({}), 19 }) 20 21 build() { 22 Column() { 23 Text('I am content') 24 .fontSize(20) 25 }.height(60).justifyContent(FlexAlign.Center) 26 } 27 } 28 ``` 292. Create a builder that is bound to the decorator. 30 31 ```ts 32 @Entry 33 @Component 34 struct CustomDialogUser { 35 dialogController: CustomDialogController = new CustomDialogController({ 36 builder: CustomDialogExample(), 37 }) 38 } 39 ``` 403. Click the component bound to the **onClick** event to display the dialog box. 41 42 ```ts 43 @Entry 44 @Component 45 struct CustomDialogUser { 46 dialogController: CustomDialogController = new CustomDialogController({ 47 builder: CustomDialogExample(), 48 }) 49 50 build() { 51 Column() { 52 Button('click me') 53 .onClick(() => { 54 this.dialogController.open() 55 }) 56 }.width('100%').margin({ top: 5 }) 57 } 58 } 59 ``` 60 61  62 63## Implementing Interaction with the Custom Dialog Box 64 65Custom dialog boxes can be used for data interactions to complete a series of operations. 66 671. Add buttons in the \@CustomDialog decorator structure and add data functions. 68 69 ```ts 70 @CustomDialog 71 struct CustomDialogExample { 72 cancel?: () => void 73 confirm?: () => void 74 controller: CustomDialogController 75 76 build() { 77 Column() { 78 Text('I am content').fontSize(20).margin({ top: 10, bottom: 10 }) 79 Flex({ justifyContent: FlexAlign.SpaceAround }) { 80 Button('Cancel') 81 .onClick(() => { 82 this.controller.close() 83 if (this.cancel) { 84 this.cancel() 85 } 86 }).backgroundColor(0xffffff).fontColor(Color.Black) 87 Button('Obtain') 88 .onClick(() => { 89 this.controller.close() 90 if (this.confirm) { 91 this.confirm() 92 } 93 }).backgroundColor(0xffffff).fontColor(Color.Red) 94 }.margin({ bottom: 10 }) 95 } 96 } 97 } 98 ``` 992. Receive the page in the builder and create corresponding function operations. 100 101 ```ts 102 @Entry 103 @Component 104 struct CustomDialogUser { 105 dialogController: CustomDialogController = new CustomDialogController({ 106 builder: CustomDialogExample({ 107 cancel: ()=> { this.onCancel() }, 108 confirm: ()=> { this.onAccept() }, 109 }), 110 }) 111 112 onCancel() { 113 console.info('Callback when the first button is clicked') 114 } 115 116 onAccept() { 117 console.info('Callback when the second button is clicked') 118 } 119 120 build() { 121 Column() { 122 Button('click me') 123 .onClick(() => { 124 this.dialogController.open() 125 }) 126 }.width('100%').margin({ top: 5 }) 127 } 128 } 129 ``` 130 131  132 133 3. Use the button in the dialog box to implement route redirection and obtain the parameters passed in from the redirection target page. 134 135 ```ts 136 // Index.ets 137 @CustomDialog 138 struct CustomDialogExample { 139 @Link textValue: string 140 controller?: CustomDialogController 141 cancel: () => void = () => { 142 } 143 confirm: () => void = () => { 144 } 145 146 build() { 147 Column({ space: 20 }) { 148 if (this.textValue != '') { 149 Text(`Content of the second page: ${this.textValue}`) 150 .fontSize(20) 151 } else { 152 Text('Obtain the content of the second page?') 153 .fontSize(20) 154 } 155 Flex({ justifyContent: FlexAlign.SpaceAround }) { 156 Button('Cancel') 157 .onClick(() => { 158 if (this.controller != undefined) { 159 this.controller.close() 160 this.cancel() 161 } 162 }).backgroundColor(0xffffff).fontColor(Color.Black) 163 Button('Obtain') 164 .onClick(() => { 165 if (this.controller != undefined && this.textValue != '') { 166 this.controller.close() 167 } else if (this.controller != undefined) { 168 this.getUIContext().getRouter().pushUrl({ 169 url: 'pages/Index2' 170 }) 171 this.controller.close() 172 } 173 }).backgroundColor(0xffffff).fontColor(Color.Red) 174 }.margin({ bottom: 10 }) 175 }.borderRadius(10).padding({ top: 20 }) 176 } 177 } 178 179 @Entry 180 @Component 181 struct CustomDialogUser { 182 @State textValue: string = '' 183 dialogController: CustomDialogController | null = new CustomDialogController({ 184 builder: CustomDialogExample({ 185 cancel: () => { 186 this.onCancel() 187 }, 188 confirm: () => { 189 this.onAccept() 190 }, 191 textValue: $textValue 192 }) 193 }) 194 195 // Set dialogController to null when the custom component is about to be destroyed. 196 aboutToDisappear() { 197 this.dialogController = null // Set dialogController to null. 198 } 199 200 onPageShow() { 201 const params = this.getUIContext().getRouter().getParams() as Record<string, string>; // Obtain the passed parameter object. 202 if (params) { 203 this.dialogController?.open() 204 this.textValue = params.info as string; // Obtain the value of the id attribute. 205 } 206 } 207 208 onCancel() { 209 console.info('Callback when the first button is clicked') 210 } 211 212 onAccept() { 213 console.info('Callback when the second button is clicked') 214 } 215 216 exitApp() { 217 console.info('Click the callback in the blank area') 218 } 219 220 build() { 221 Column() { 222 Button('Click Me') 223 .onClick(() => { 224 if (this.dialogController != null) { 225 this.dialogController.open() 226 } 227 }).backgroundColor(0x317aff) 228 }.width('100%').margin({ top: 5 }) 229 } 230 } 231 ``` 232 233 ```ts 234 // Index2.ets 235 @Entry 236 @Component 237 struct Index2 { 238 @State message: string =' Back'; 239 240 build() { 241 Column() { 242 Button(this.message) 243 .type(ButtonType.Capsule) 244 .onClick(() => { 245 this.getUIContext().getRouter().back({ 246 url: 'pages/Index', 247 params: { 248 info: 'Hello World' 249 } 250 }); 251 }) 252 }.width('100%').height('100%').margin({ top: 20 }) 253 } 254 } 255 ``` 256 257  258 259## Defining the Custom Dialog Box Animation 260 261You can define the custom dialog box animation, including its duration and speed, through **openAnimation**. 262 263```ts 264@CustomDialog 265struct CustomDialogExample { 266 controller?: CustomDialogController 267 268 build() { 269 Column() { 270 Text('Whether to change a text?').fontSize(16).margin({ bottom: 10 }) 271 } 272 } 273} 274 275@Entry 276@Component 277struct CustomDialogUser { 278 @State textValue: string = '' 279 @State inputValue: string = 'click me' 280 dialogController: CustomDialogController | null = new CustomDialogController({ 281 builder: CustomDialogExample(), 282 openAnimation: { 283 duration: 1200, 284 curve: Curve.Friction, 285 delay: 500, 286 playMode: PlayMode.Alternate, 287 onFinish: () => { 288 console.info('play end') 289 } 290 }, 291 autoCancel: true, 292 alignment: DialogAlignment.Bottom, 293 offset: { dx: 0, dy: -20 }, 294 gridCount: 4, 295 customStyle: false, 296 backgroundColor: 0xd9ffffff, 297 cornerRadius: 10, 298 }) 299 300 // Set dialogController to null when the custom component is about to be destroyed. 301 aboutToDisappear() { 302 this.dialogController = null // Set dialogController to null. 303 } 304 305 build() { 306 Column() { 307 Button(this.inputValue) 308 .onClick(() => { 309 if (this.dialogController != null) { 310 this.dialogController.open() 311 } 312 }).backgroundColor(0x317aff) 313 }.width('100%').margin({ top: 5 }) 314 } 315} 316``` 317 318 319 320## Defining the Custom Dialog Box Style 321 322You can set style parameters, such as the width, height, background color, and shadow, for a custom dialog box. 323 324```ts 325@CustomDialog 326struct CustomDialogExample { 327 controller?: CustomDialogController 328 329 build() { 330 Column() { 331 Text('I am content').fontSize(16).margin({ bottom: 10 }) 332 } 333 } 334} 335 336@Entry 337@Component 338struct CustomDialogUser { 339 @State textValue: string = '' 340 @State inputValue: string = 'Click Me' 341 dialogController: CustomDialogController | null = new CustomDialogController({ 342 builder: CustomDialogExample(), 343 autoCancel: true, 344 alignment: DialogAlignment.Center, 345 offset: { dx: 0, dy: -20 }, 346 gridCount: 4, 347 customStyle: false, 348 backgroundColor: 0xd9ffffff, 349 cornerRadius: 20, 350 width: '80%', 351 height: '100px', 352 borderWidth: 1, 353 borderStyle: BorderStyle.Dashed,// borderStyle must be used with borderWidth in pairs. 354 borderColor: Color.Blue,// borderColor must be used with borderWidth in pairs. 355 shadow: ({ radius: 20, color: Color.Grey, offsetX: 50, offsetY: 0}), 356 }) 357 358 // Set dialogController to null when the custom component is about to be destroyed. 359 aboutToDisappear() { 360 this.dialogController = null // Set dialogController to null. 361 } 362 363 build() { 364 Column() { 365 Button(this.inputValue) 366 .onClick(() => { 367 if (this.dialogController != null) { 368 this.dialogController.open() 369 } 370 }).backgroundColor(0x317aff) 371 }.width('100%').margin({ top: 5 }) 372 } 373} 374``` 375 376 377 378## Nesting a Custom Dialog Box 379 380To nest a dialog box (dialog 2) inside another dialog box (dialog 1), it is recommended that you define dialog 2 within the parent component of dialog 1 so that you can then open dialog 2 through the callback sent from the parent component to dialog 1. 381 382```ts 383@CustomDialog 384struct CustomDialogExampleTwo { 385 controllerTwo?: CustomDialogController 386 @State message: string = "I'm the second dialog box." 387 @State showIf: boolean = false; 388 build() { 389 Column() { 390 if (this.showIf) { 391 Text("Text") 392 .fontSize(30) 393 .height(100) 394 } 395 Text(this.message) 396 .fontSize(30) 397 .height(100) 398 Button("Create Text") 399 .onClick(()=>{ 400 this.showIf = true; 401 }) 402 Button('Close Second Dialog Box') 403 .onClick(() => { 404 if (this.controllerTwo != undefined) { 405 this.controllerTwo.close() 406 } 407 }) 408 .margin(20) 409 } 410 } 411} 412@CustomDialog 413struct CustomDialogExample { 414 openSecondBox?: ()=>void 415 controller?: CustomDialogController 416 417 build() { 418 Column() { 419 Button('Open Second Dialog Box and Close This Box') 420 .onClick(() => { 421 this.controller!.close(); 422 this.openSecondBox!(); 423 }) 424 .margin(20) 425 }.borderRadius(10) 426 } 427} 428@Entry 429@Component 430struct CustomDialogUser { 431 @State inputValue: string = 'Click Me' 432 dialogController: CustomDialogController | null = new CustomDialogController({ 433 builder: CustomDialogExample({ 434 openSecondBox: ()=>{ 435 if (this.dialogControllerTwo != null) { 436 this.dialogControllerTwo.open() 437 } 438 } 439 }), 440 cancel: this.exitApp, 441 autoCancel: true, 442 alignment: DialogAlignment.Bottom, 443 offset: { dx: 0, dy: -20 }, 444 gridCount: 4, 445 customStyle: false 446 }) 447 dialogControllerTwo: CustomDialogController | null = new CustomDialogController({ 448 builder: CustomDialogExampleTwo(), 449 alignment: DialogAlignment.Bottom, 450 offset: { dx: 0, dy: -25 } }) 451 452 aboutToDisappear() { 453 this.dialogController = null 454 this.dialogControllerTwo = null 455 } 456 457 onCancel() { 458 console.info('Callback when the first button is clicked') 459 } 460 461 onAccept() { 462 console.info('Callback when the second button is clicked') 463 } 464 465 exitApp() { 466 console.info('Click the callback in the blank area') 467 } 468 build() { 469 Column() { 470 Button(this.inputValue) 471 .onClick(() => { 472 if (this.dialogController != null) { 473 this.dialogController.open() 474 } 475 }).backgroundColor(0x317aff) 476 }.width('100%').margin({ top: 5 }) 477 } 478} 479``` 480 481 482 483If you define dialog 2 within dialog 1 instead, because of the parent-child relationship that exists between custom dialog boxes in terms of state management, you will not be able to create any component in dialog 2 once dialog 1 is destroyed (closed). 484 485