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** component. For details, see the [page display mode: dialog mode](arkts-navigation-navigation.md#page-display-mode). 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 build() { 240 Column() { 241 Button(this.message) 242 .fontWeight(FontWeight.Bold).onClick(() => { 243 this.getUIContext().getRouter().back({ 244 url: 'pages/Index', 245 params: { 246 info: 'Hello World' 247 } 248 }); 249 }) 250 }.width('100%').height('100%').margin({ top: 20 }) 251 } 252 } 253 ``` 254 255  256 257## Defining the Custom Dialog Box Animation 258 259You can define the custom dialog box animation, including its duration and speed, through **openAnimation**. 260 261```ts 262@CustomDialog 263struct CustomDialogExample { 264 controller?: CustomDialogController 265 266 build() { 267 Column() { 268 Text('Whether to change a text?').fontSize(16).margin({ bottom: 10 }) 269 } 270 } 271} 272 273@Entry 274@Component 275struct CustomDialogUser { 276 @State textValue: string = '' 277 @State inputValue: string = 'click me' 278 dialogController: CustomDialogController | null = new CustomDialogController({ 279 builder: CustomDialogExample(), 280 openAnimation: { 281 duration: 1200, 282 curve: Curve.Friction, 283 delay: 500, 284 playMode: PlayMode.Alternate, 285 onFinish: () => { 286 console.info('play end') 287 } 288 }, 289 autoCancel: true, 290 alignment: DialogAlignment.Bottom, 291 offset: { dx: 0, dy: -20 }, 292 gridCount: 4, 293 customStyle: false, 294 backgroundColor: 0xd9ffffff, 295 cornerRadius: 10, 296 }) 297 298 // Set dialogController to null when the custom component is about to be destroyed. 299 aboutToDisappear() { 300 this.dialogController = null // Set dialogController to null. 301 } 302 303 build() { 304 Column() { 305 Button(this.inputValue) 306 .onClick(() => { 307 if (this.dialogController != null) { 308 this.dialogController.open() 309 } 310 }).backgroundColor(0x317aff) 311 }.width('100%').margin({ top: 5 }) 312 } 313} 314``` 315 316 317 318## Defining the Custom Dialog Box Style 319 320You can set style parameters, such as the width, height, background color, and shadow, for a custom dialog box. 321 322```ts 323@CustomDialog 324struct CustomDialogExample { 325 controller?: CustomDialogController 326 327 build() { 328 Column() { 329 Text('I am content').fontSize(16).margin({ bottom: 10 }) 330 } 331 } 332} 333 334@Entry 335@Component 336struct CustomDialogUser { 337 @State textValue: string = '' 338 @State inputValue: string = 'Click Me' 339 dialogController: CustomDialogController | null = new CustomDialogController({ 340 builder: CustomDialogExample(), 341 autoCancel: true, 342 alignment: DialogAlignment.Center, 343 offset: { dx: 0, dy: -20 }, 344 gridCount: 4, 345 customStyle: false, 346 backgroundColor: 0xd9ffffff, 347 cornerRadius: 20, 348 width: '80%', 349 height: '100px', 350 borderWidth: 1, 351 borderStyle: BorderStyle.Dashed,// borderStyle must be used with borderWidth in pairs. 352 borderColor: Color.Blue,// borderColor must be used with borderWidth in pairs. 353 shadow: ({ radius: 20, color: Color.Grey, offsetX: 50, offsetY: 0}), 354 }) 355 356 // Set dialogController to null when the custom component is about to be destroyed. 357 aboutToDisappear() { 358 this.dialogController = null // Set dialogController to null. 359 } 360 361 build() { 362 Column() { 363 Button(this.inputValue) 364 .onClick(() => { 365 if (this.dialogController != null) { 366 this.dialogController.open() 367 } 368 }).backgroundColor(0x317aff) 369 }.width('100%').margin({ top: 5 }) 370 } 371} 372``` 373 374 375 376## Nesting a Custom Dialog Box 377 378To 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. 379 380```ts 381@CustomDialog 382struct CustomDialogExampleTwo { 383 controllerTwo?: CustomDialogController 384 @State message: string = "I'm the second dialog box." 385 @State showIf: boolean = false; 386 build() { 387 Column() { 388 if (this.showIf) { 389 Text("Text") 390 .fontSize(30) 391 .height(100) 392 } 393 Text(this.message) 394 .fontSize(30) 395 .height(100) 396 Button("Create Text") 397 .onClick(()=>{ 398 this.showIf = true; 399 }) 400 Button('Close Second Dialog Box') 401 .onClick(() => { 402 if (this.controllerTwo != undefined) { 403 this.controllerTwo.close() 404 } 405 }) 406 .margin(20) 407 } 408 } 409} 410@CustomDialog 411struct CustomDialogExample { 412 openSecondBox?: ()=>void 413 controller?: CustomDialogController 414 415 build() { 416 Column() { 417 Button('Open Second Dialog Box and Close This Box') 418 .onClick(() => { 419 this.controller!.close(); 420 this.openSecondBox!(); 421 }) 422 .margin(20) 423 }.borderRadius(10) 424 } 425} 426@Entry 427@Component 428struct CustomDialogUser { 429 @State inputValue: string = 'Click Me' 430 dialogController: CustomDialogController | null = new CustomDialogController({ 431 builder: CustomDialogExample({ 432 openSecondBox: ()=>{ 433 if (this.dialogControllerTwo != null) { 434 this.dialogControllerTwo.open() 435 } 436 } 437 }), 438 cancel: this.exitApp, 439 autoCancel: true, 440 alignment: DialogAlignment.Bottom, 441 offset: { dx: 0, dy: -20 }, 442 gridCount: 4, 443 customStyle: false 444 }) 445 dialogControllerTwo: CustomDialogController | null = new CustomDialogController({ 446 builder: CustomDialogExampleTwo(), 447 alignment: DialogAlignment.Bottom, 448 offset: { dx: 0, dy: -25 } }) 449 450 aboutToDisappear() { 451 this.dialogController = null 452 this.dialogControllerTwo = null 453 } 454 455 onCancel() { 456 console.info('Callback when the first button is clicked') 457 } 458 459 onAccept() { 460 console.info('Callback when the second button is clicked') 461 } 462 463 exitApp() { 464 console.info('Click the callback in the blank area') 465 } 466 build() { 467 Column() { 468 Button(this.inputValue) 469 .onClick(() => { 470 if (this.dialogController != null) { 471 this.dialogController.open() 472 } 473 }).backgroundColor(0x317aff) 474 }.width('100%').margin({ top: 5 }) 475 } 476} 477``` 478 479 480 481If 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). 482 483