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