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 .margin({ top: 10, bottom: 10 }) 26 } 27 } 28 } 29 ``` 302. Create a builder that is bound to the decorator. 31 32 ```ts 33 @Entry 34 @Component 35 struct CustomDialogUser { 36 dialogController: CustomDialogController = new CustomDialogController({ 37 builder: CustomDialogExample(), 38 }) 39 } 40 ``` 413. Click the component bound to the **onClick** event to display the dialog box. 42 43 ```ts 44 @Entry 45 @Component 46 struct CustomDialogUser { 47 dialogController: CustomDialogController = new CustomDialogController({ 48 builder: CustomDialogExample(), 49 }) 50 51 build() { 52 Column() { 53 Button('click me') 54 .onClick(() => { 55 this.dialogController.open() 56 }) 57 }.width('100%').margin({ top: 5 }) 58 } 59 } 60 ``` 61 62  63 64## Implementing Interaction with the Custom Dialog Box 65 66Custom dialog boxes can be used for data interactions to complete a series of operations. 67 681. Add buttons in the \@CustomDialog decorator structure and add data functions. 69 70 ```ts 71 @CustomDialog 72 struct CustomDialogExample { 73 cancel?: () => void 74 confirm?: () => void 75 controller: CustomDialogController 76 77 build() { 78 Column() { 79 Text('I am content').fontSize(20).margin({ top: 10, bottom: 10 }) 80 Flex({ justifyContent: FlexAlign.SpaceAround }) { 81 Button('Cancel') 82 .onClick(() => { 83 this.controller.close() 84 if (this.cancel) { 85 this.cancel() 86 } 87 }).backgroundColor(0xffffff).fontColor(Color.Black) 88 Button('Obtain') 89 .onClick(() => { 90 this.controller.close() 91 if (this.confirm) { 92 this.confirm() 93 } 94 }).backgroundColor(0xffffff).fontColor(Color.Red) 95 }.margin({ bottom: 10 }) 96 } 97 } 98 } 99 ``` 1002. Receive the page in the builder and create corresponding function operations. 101 102 ```ts 103 @Entry 104 @Component 105 struct CustomDialogUser { 106 dialogController: CustomDialogController = new CustomDialogController({ 107 builder: CustomDialogExample({ 108 cancel: ()=> { this.onCancel() }, 109 confirm: ()=> { this.onAccept() }, 110 }), 111 }) 112 113 onCancel() { 114 console.info('Callback when the first button is clicked') 115 } 116 117 onAccept() { 118 console.info('Callback when the second button is clicked') 119 } 120 121 build() { 122 Column() { 123 Button('click me') 124 .onClick(() => { 125 this.dialogController.open() 126 }) 127 }.width('100%').margin({ top: 5 }) 128 } 129 } 130 ``` 131 132  133 134 3. Use the button in the dialog box to implement route redirection and obtain the parameters passed in from the redirection target page. 135 136 ```ts 137 // Index.ets 138 @CustomDialog 139 struct CustomDialogExample { 140 @Link textValue: string 141 controller?: CustomDialogController 142 cancel: () => void = () => { 143 } 144 confirm: () => void = () => { 145 } 146 147 build() { 148 Column({ space: 20 }) { 149 if (this.textValue != '') { 150 Text(`Content of the second page: ${this.textValue}`) 151 .fontSize(20) 152 } else { 153 Text('Obtain the content of the second page?') 154 .fontSize(20) 155 } 156 Flex({ justifyContent: FlexAlign.SpaceAround }) { 157 Button('Cancel') 158 .onClick(() => { 159 if (this.controller != undefined) { 160 this.controller.close() 161 this.cancel() 162 } 163 }).backgroundColor(0xffffff).fontColor(Color.Black) 164 Button('Obtain') 165 .onClick(() => { 166 if (this.controller != undefined && this.textValue != '') { 167 this.controller.close() 168 } else if (this.controller != undefined) { 169 this.getUIContext().getRouter().pushUrl({ 170 url: 'pages/Index2' 171 }) 172 this.controller.close() 173 } 174 }).backgroundColor(0xffffff).fontColor(Color.Red) 175 }.margin({ bottom: 10 }) 176 }.borderRadius(10).padding({ top: 20 }) 177 } 178 } 179 180 @Entry 181 @Component 182 struct CustomDialogUser { 183 @State textValue: string = '' 184 dialogController: CustomDialogController | null = new CustomDialogController({ 185 builder: CustomDialogExample({ 186 cancel: () => { 187 this.onCancel() 188 }, 189 confirm: () => { 190 this.onAccept() 191 }, 192 textValue: $textValue 193 }) 194 }) 195 196 // Set dialogController to null when the custom component is about to be destroyed. 197 aboutToDisappear() { 198 this.dialogController = null // Set dialogController to null. 199 } 200 201 onPageShow() { 202 const params = this.getUIContext().getRouter().getParams() as Record<string, string>; // Obtain the passed parameter object. 203 if (params) { 204 this.dialogController?.open() 205 this.textValue = params.info as string; // Obtain the value of the id attribute. 206 } 207 } 208 209 onCancel() { 210 console.info('Callback when the first button is clicked') 211 } 212 213 onAccept() { 214 console.info('Callback when the second button is clicked') 215 } 216 217 exitApp() { 218 console.info('Click the callback in the blank area') 219 } 220 221 build() { 222 Column() { 223 Button('click me') 224 .onClick(() => { 225 if (this.dialogController != null) { 226 this.dialogController.open() 227 } 228 }).backgroundColor(0x317aff) 229 }.width('100%').margin({ top: 5 }) 230 } 231 } 232 ``` 233 234 ```ts 235 // Index2.ets 236 @Entry 237 @Component 238 struct Index2 { 239 @State message: string =' Back'; 240 build() { 241 Column() { 242 Button(this.message) 243 .fontSize(50) 244 .fontWeight(FontWeight.Bold).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