1# ArkUI Development 2 3## How do I dynamically replace the %s placeholder in a resource file? 4 5Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 6 7**Symptom** 8 9How do I dynamically replace the %s placeholder in a resource file? 10 11**Solution** 12 13In an application, you can replace the **%s** placeholder by using the second parameter in **$r('app.string.xx')**, which is used to reference application resources. 14 15**Example** 16 17``` 18build() { 19 //do something 20 // The second parameter indicates the referenced string resource, which can be used to replace the %s placeholder. 21 Text($r('app.string.entry_desc','aaa')) 22 .fontSize(100) 23 .fontColor(Color.Black) 24 //do something 25} 26``` 27 28## Can custom dialog boxes be defined or used in .ts files? 29 30Applicable to: OpenHarmony 3.2 Beta5 (API version 9, stage model) 31 32Unfortunately, no. ArkTS syntax is required for defining and initializing custom dialog boxes. Therefore, they can be defined and used only in .ets files. 33 34**Reference** 35 36[Custom Dialog Box](../reference/arkui-ts/ts-methods-custom-dialog-box.md) 37 38## How do I transfer variables in a custom dialog box to a page? 39 40Applicable to: OpenHarmony 3.2 Beta5 (API version 9, stage model) 41 42**Symptom** 43 44The variable defined in a custom dialog box needs to be transferred to the page when the dialog box is closed or the variable changes. 45 46**Solution** 47 48- Method 1: Define the variable as a state variable of the custom dialog box. 49- Method 2: During initialization of the custom dialog box, pass to it a method, which is triggered in the custom dialog box and accepts the variable in the custom dialog box as a parameter. 50- Method 3: Use AppStorage or LocalStorage to manage page state and implement state sharing between the custom dialog box and page. 51 52**Example** 53 54- Method 1: 55 56 ``` 57 @CustomDialog 58 struct CustomDialog01 { 59 @Link inputValue: string 60 controller: CustomDialogController 61 build() { 62 Column() { 63 Text('Change text').fontSize(20).margin({ top: 10, bottom: 10 }) 64 TextInput({ placeholder: '', text: this.inputValue }).height(60).width('90%') 65 .onChange((value: string) => { 66 this.inputValue = value 67 }) 68 } 69 } 70 } 71 72 @Entry 73 @Component 74 struct DialogDemo01 { 75 @State inputValue: string = 'click me' 76 dialogController: CustomDialogController = new CustomDialogController({ 77 builder: CustomDialog01({ 78 inputValue: $inputValue 79 }) 80 }) 81 82 build() { 83 Column() { 84 Button(this.inputValue) 85 .onClick(() => { 86 this.dialogController.open() 87 }).backgroundColor(0x317aff) 88 }.width('100%').margin({ top: 5 }) 89 } 90 } 91 92 ``` 93 94- Method 2: 95 96 ``` 97 @CustomDialog 98 struct CustomDialog02 { 99 private inputValue: string 100 changeInputValue: (val: string) => void 101 controller: CustomDialogController 102 build() { 103 Column() { 104 Text('Change text').fontSize(20).margin({ top: 10, bottom: 10 }) 105 TextInput({ placeholder: '', text: this.inputValue }).height(60).width('90%') 106 .onChange((value: string) => { 107 this.changeInputValue(value) 108 }) 109 } 110 } 111 } 112 113 @Entry 114 @Component 115 struct DialogDemo02 { 116 @State inputValue: string = 'click me' 117 dialogController: CustomDialogController = new CustomDialogController({ 118 builder: CustomDialog02({ 119 inputValue: this.inputValue, 120 changeInputValue: (val: string) => { 121 this.inputValue = val 122 } 123 }) 124 }) 125 126 build() { 127 Column() { 128 Button(this.inputValue) 129 .onClick(() => { 130 this.dialogController.open() 131 }).backgroundColor(0x317aff) 132 }.width('100%').margin({ top: 5 }) 133 } 134 } 135 136 ``` 137 138- Method 3: 139 140 ``` 141 let storage = LocalStorage.GetShared() 142 @CustomDialog 143 struct CustomDialog03 { 144 @LocalStorageLink('inputVal') inputValue: string = '' 145 controller: CustomDialogController 146 build() { 147 Column() { 148 Text('Change text').fontSize(20).margin({ top: 10, bottom: 10 }) 149 TextInput({ placeholder: '', text: this.inputValue }).height(60).width('90%') 150 .onChange((value: string) => { 151 this.inputValue = value; 152 }) 153 } 154 } 155 } 156 157 @Entry(storage) 158 @Component 159 struct DialogDemo03 { 160 @LocalStorageLink('inputVal') inputValue: string = '' 161 dialogController: CustomDialogController = new CustomDialogController({ 162 builder: CustomDialog03() 163 }) 164 165 build() { 166 Column() { 167 Button(this.inputValue) 168 .onClick(() => { 169 this.dialogController.open() 170 }).backgroundColor(0x317aff) 171 }.width('100%').margin({ top: 5 }) 172 } 173 } 174 175 ``` 176 177 178## How do I obtain the width and height of a component? 179 180Applicable to: OpenHarmony 3.2 Beta5 (API version 9, stage model) 181 182**Symptom** 183 184The width and height of a component need to be obtained to calculate the size and offset of the layout area. 185 186**Solution** 187 188- Method 1: Use the **onAreaChange** event of the component, which is triggered when the component is initialized or the component size changes. 189- Manner 2: Use the callback in the click or touch event, which provides the area information of the target element. 190 191**Reference** 192 193[Component Area Change Event](../reference/arkui-ts/ts-universal-component-area-change-event.md), [Click Event](../reference/arkui-ts/ts-universal-events-click.md), [Touch Event](../reference/arkui-ts/ts-universal-events-touch.md) 194 195## How do I clear the content of the \<TextInput> and \<TextArea> components by one click? 196 197Applicable to: OpenHarmony 3.2 Beta5 (API version 9, stage model) 198 199**Symptom** 200 201A click-to-clear feature is required to remove all characters in the **\<TextInput>** and **\<TextArea>** component at once. 202 203**Solution** 204 205Convert the **text** attribute of the **\<TextInput>** and **\<TextArea>** component to a state variable. Assign an empty string to the state variable when the click-to-clear event is performed. 206 207**Example** 208 209``` 210struct Index { 211@State text: string = 'Hello World' 212controller: TextInputController = new TextInputController() 213 build() { 214 Row() { 215 Column() { 216 TextInput({ placeholder: 'Please input your words.', text: this.text, 217 controller:this.controller}).onChange((value) => { 218 this.text = value 219 }) 220 Button("Clear TextInput").onClick(() => { 221 this.text = ""; 222 }) 223 } 224 .width('100%') 225 } 226 .height('100%') 227 } 228} 229``` 230 231## How do I set the position of a custom dialog box? 232 233Applicable to: OpenHarmony 3.2 Beta5 (API version 9, stage model) 234 235**Symptom** 236 237By default, a custom dialog box is displayed in the center of the window. In some cases, it needs to be aligned with the window border. 238 239**Solution** 240 241During initialization of the custom dialog box, set the **alignment** and **offset** parameters. 242 243**Reference** 244 245[Custom Dialog Box](../reference/arkui-ts/ts-methods-custom-dialog-box.md) 246 247## How do I hide the overflow content of a container component? 248 249Applicable to: OpenHarmony 3.2 Beta5 (API version 9, stage model) 250 251**Symptom** 252 253When content overflows in a container component, that is, the child component does not fit in the container component, the overflow content needs to be processed. 254 255**Solution** 256 257To clip and hide overflow content, set the **clip** universal attribute to **true**. By default, this attribute is set to **false**. 258 259**Reference** 260 261[Shape Clipping](../reference/arkui-ts/ts-universal-attributes-sharp-clipping.md) 262 263 264## How do I set a custom dialog box to automatically adapt its size to content? 265 266Applicable to: OpenHarmony 3.2 Beta5 (API version 9, stage model) 267 268**Symptom** 269 270When a custom dialog box contains a child component whose area size can be changed, it needs to automatically adjust its size. 271 272**Solution** 273 274- Method 1: Use the default style of the custom dialog box. In this case, the dialog box automatically adapts its width to the grid system and its height to the child components; the maximum height is 90% of the container height. 275- Method 2: Use a custom style of the custom dialog box. In this case, the dialog box automatically adapts its width and height to the child components. 276 277**Reference** 278 279[Custom Dialog Box](../reference/arkui-ts/ts-methods-custom-dialog-box.md) 280 281## What is the function of the gridCount parameter in the custom dialog box? 282 283Applicable to: OpenHarmony 3.2 Beta5 (API version 9, stage model) 284 285The **gridCount** parameter indicates the number of grid columns occupied by the dialog box. The system divides the window width into equal regions. The number of equal regions is the number of grid columns, which varies by device. For example, if the screen density of a phone is 320 vp <= horizontal width < 600 vp, the number of grid columns is 4, and the valid value of **gridCount** is \[1, 4\]. 286 287Note: This parameter is valid only when the custom dialog box is in the default style. 288 289**Reference** 290 291[Custom Dialog Box](../reference/arkui-ts/ts-methods-custom-dialog-box.md) 292 293## How do I remove the white background of a custom dialog box? 294 295Applicable to: OpenHarmony 3.2 Beta5 (API version 9, stage model) 296 297**Symptom** 298 299When in the default style a custom dialog box comes with a white background. 300 301**Solution** 302 303To remove the white background, set the custom dialog box to a custom style. 304 3051. During initialization of the custom dialog box, set **customStyle** to **true**. 3062. During initialization of the custom dialog box, set **backgroundColor** to the color you prefer. 307 308**Reference** 309 310[Custom Dialog Box](../reference/arkui-ts/ts-methods-custom-dialog-box.md) 311 312## How do I customize the eye icon for the password input mode of the \<TextInput> component? 313 314Applicable to: OpenHarmony 3.2 Beta5 (API version 9, stage model) 315 316**Symptom** 317 318The eye icon for the password input mode (with the **type** attribute of the **\<TextInput>** component set to **InputType.Password**) cannot be customized. 319 320**Solution** 321 322The eye icon itself cannot be customized. You can use set the **showPasswordIcon** attribute of the **\<TextInput>** component to **false** to hide the icon, and use the **\<Image>** component to control the type of the **\<TextInput>** component. 323 324**Reference** 325 326[TextInput](../reference/arkui-ts/ts-basic-components-textinput.md) 327 328## How do I use the onSubmit event of the \<TextInput> component? 329 330Applicable to: OpenHarmony 3.2 Beta5 (API version 9, stage model) 331 332**Solution** 333 334The **onSubmit** event is triggered when a user presses **Enter** on the (physical or soft) keyboard. The callback parameter in the event is the current Enter key type. The Enter key type can be set through the **enterKeyType** attribute of the **\<TextInput>** component. Setting the key style of the soft keyboard requires support by the input method. 335 336**Reference** 337 338[TextInput](../reference/arkui-ts/ts-basic-components-textinput.md) 339 340## How do I set the caret position to the start point for when the \<TextInput> component obtains focus? 341 342Applicable to: OpenHarmony 3.2 Beta5 (API version 9, stage model) 343 344**Symptom** 345 346When the **\<TextInput>** component obtains focus, the caret automatically moves to the position of the touch point, instead of the start position. 347 348**Solution** 349 3501. Bind the **\<TextInput>** component to the **onEditChange** event, which is triggered when the component enters the input state. 3512. Call the **setTimeout** API for asynchronous processing. Then call the **TextInputController.caretPosition** API in the event callback to set the caret position. 352 353**Example** 354 355``` 356@Entry 357@Component 358struct TextInputDemo { 359 controller: TextInputController = new TextInputController() 360 361 build() { 362 Column() { 363 TextInput({ controller: this.controller }) 364 .onEditChange((isEditing: boolean) => { 365 if (isEditing) { 366 setTimeout(() => { 367 this.controller.caretPosition(0) 368 }, 100) 369 } 370 }) 371 } 372 } 373} 374``` 375 376**Reference** 377 378[TextInput](../reference/arkui-ts/ts-basic-components-textinput.md) 379 380## How do I obtain component attribute information? 381 382Applicable to: OpenHarmony 3.2 Beta5 (API version 9, stage model) 383 384**Solution** 385 386To obtain all attributes of a component, use **getInspectorByKey**. 387 388**Reference** 389 390[Component ID](../reference/arkui-ts/ts-universal-attributes-component-id.md) 391 392## How do I obtain the current scrolling offset of a scrollable component? 393 394Applicable to: OpenHarmony 3.2 Beta5 (API version 9, stage model) 395 396**Solution** 397 3981. During initialization of the scrollable component, such as **\<List>**, **\<Grid>**, and **\<Scroll>**, set the **scroller** parameter to bind the component to a scroll controller. 3992. Call the **currentOffset** API of the controller to obtain the horizontal and vertical scrolling offsets. 400 401**Reference** 402 403[Scroll](../reference/arkui-ts/ts-container-scroll.md#currentoffset) 404 405## How do I align text vertically? 406 407Applicable to: OpenHarmony 3.2 Beta5 (API version 9, stage model) 408 409**Symptom** 410 411Text cannot be aligned vertically in the **\<Text>** component. 412 413**Solution** 414 415Text is aligned horizontally in the **\<Text>** component. To enable text to align vertically, you can split the file, use the **\<Flex>** container component, and set its main axis direction to vertical. 416 417**Example** 418 419``` 420@Entry 421@Component 422struct Index15 { 423 private message: string = 'This document is intended for novices in developing applications. It introduces you to the application development process and main files in the project director, by walking you through the building of a simple application with the page redirection/return feature.'; 424 build() { 425 Flex({ direction: FlexDirection.Column, wrap: FlexWrap.Wrap }) { 426 ForEach(this.message.split(''), (item, index) => { 427 Text(item) 428 .fontSize(30) 429 .flexShrink(0) 430 }) 431 } 432 } 433} 434``` 435 436## How do I create a toast window? 437 438Applicable to: OpenHarmony 3.2 Beta5 (API version 9, stage model) 439 440**Symptom** 441 442A toast window is required for delivering a toast message. 443 444**Solution** 445 446To create a toast window, use the **@ohos.promptAction** API. 447 448**Reference** 449 450[@ohos.promptAction (Prompt)](../reference/apis/js-apis-promptAction.md) 451 452## Can I set the background or font color for the toast window? 453 454Applicable to: OpenHarmony 3.2 Beta5 (API version 9, stage model) 455 456This feature is not supported currently. 457 458**Reference** 459 460[@ohos.promptAction (Prompt)](../reference/apis/js-apis-promptAction.md) 461 462## How do I set the UI of an ability to transparent? 463 464Applicable to: OpenHarmony 3.2 (API version 9) 465 466**Solution** 467 468Set the background color of the top container component to transparent, and then set the **opacity** attribute of the XComponent to **0.01**. 469 470Example: 471 472``` 473build() { 474 Stack() { 475 XComponent({ 476 id: 'componentId', 477 type: 'surface', 478 }) 479 .width('100%') 480 .height('100%') 481 .opacity(0.01) 482 // Page content 483 } 484 .width('100%') 485 .height('100%') 486 .backgroundColor('rgba(255,255,255, 0)') 487} 488``` 489 490## Why do the constraintSize settings fail to take effect? 491 492Applicable to: OpenHarmony 3.2 Beta5 (API version 9, stage model) 493 494**Symptom** 495 496If **constraintSize** is set for a component and the width of its child component is set to a percentage, for example, **width\('100%'\)**, **constraintSize** takes effect by multiplying the maximum width by the percentage. As a result, the child component may overflow, in which case it looks like the **constraintSize** settings fail to take effect. 497 498**Solution** 499 500You can use the **\<Scroll>** component at the outer layer. In this way, when **constraintSize** is set and the space occupied by a child component exceeds the specified constraint value, a scrollbar will be displayed. 501 502## How do I set the background color to transparent? 503 504Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 505 506**Solution** 507 508Set **backgroundColor** to **'\#00000000'**. 509 510## What should I do if the \<Scroll> component cannot scroll to the bottom? 511 512Applicable to: OpenHarmony 3.2 Beta5 (API version 9, stage model) 513 514**Symptom** 515 516Unless otherwise specified, the height of the **\<Scroll>** component is equal to the window height. In this case, the component's bottom area will be blocked by components (if any) outside of it. 517 518**Solution** 519 520Set the height of the **\<Scroll>** component or use the flex layout to limit this height. 521 522## What is the counterpart of CenterCrop in OpenHarmony for backgroundImage? 523 524Applicable to: OpenHarmony 3.2 Beta5 (API version 9, stage model) 525 526**Solution** 527 528To achieve the equivalent effect CenterCrop – place the image in the center of the window and scale the image while maintaining its aspect ratio, you can use the universal attributes **backgroundImageSize**\(**ImageSize.cover**\) and **backgroundImagePosition** \(**Alignment.Center**\). 529 530## How do I customize the control bar style of the \<Video> component? 531 532Applicable to: OpenHarmony 3.2 Beta5 (API version 9, stage model) 533 534**Solution** 535 5361. Set **controls** to **false** to disable the default control bar. 537 5382. Sets **controller** for the **\<Video>** component. 539 5403. Implement a custom control bar in ArkTS and use **VideoController** to control video playback. 541 542**Example** 543 544``` 545// xxx.ets 546@Entry@Componentstruct VideoCreateComponent { 547 @State videoSrc: Resource = $rawfile('video1.mp4') 548 @State previewUri: Resource = $r('app.media.poster1') 549 @State curRate: PlaybackSpeed = PlaybackSpeed.Speed_Forward_1_00_X 550 @State isAutoPlay: boolean = false 551 @State showControls: boolean = true 552 controller: VideoController = new VideoController() 553 build() { 554 Column() { 555 Video({ 556 src: this.videoSrc, 557 previewUri: this.previewUri, 558 currentProgressRate: this.curRate, 559 controller: this.controller 560 }).width('100%').height(600) 561 .autoPlay(this.isAutoPlay) 562 .controls(this.showControls) 563 .onStart(() => { 564 console.info('onStart') 565 }) 566 .onPause(() => { 567 console.info('onPause') 568 }) 569 .onFinish(() => { 570 console.info('onFinish') 571 }) 572 .onError(() => { 573 console.info('onError') 574 }) 575 .onPrepared((e) => { 576 console.info('onPrepared is ' + e.duration) 577 }) 578 .onSeeking((e) => { 579 console.info('onSeeking is ' + e.time) 580 }) 581 .onSeeked((e) => { 582 console.info('onSeeked is ' + e.time) 583 }) 584 .onUpdate((e) => { 585 console.info('onUpdate is ' + e.time) 586 }) 587 Row() { 588 Button('src').onClick(() => { 589 this.videoSrc = $rawfile('video2.mp4') // Switch the video source. 590 }).margin(5) 591 Button('previewUri').onClick(() => { 592 this.previewUri = $r('app.media.poster2') // Switch the preview image. 593 }).margin(5) 594 595 Button('controls').onClick(() => { 596 this.showControls =! this.showControls // Specify whether to show the control bar. 597 }).margin(5) 598 } 599 Row() { 600 Button('start').onClick(() => { 601 this.controller.start() // Start playback. 602 }).margin(5) 603 Button('pause').onClick(() => { 604 this.controller.pause() // Pause playback. 605 }).margin(5) 606 Button('stop').onClick(() => { 607 this.controller.stop() // Stop playback. 608 }).margin(5) 609 Button('setTime').onClick(() => { 610 this.controller.setCurrentTime(10, SeekMode.Accurate) // Seek to the 10s position of the video. 611 }).margin(5) 612 } 613 Row() { 614 Button('rate 0.75').onClick(() => { 615 this.curRate = PlaybackSpeed.Speed_Forward_0_75_X // Play the video at the 0.75x speed. 616 }).margin(5) 617 Button('rate 1').onClick(() => { 618 this.curRate = PlaybackSpeed.Speed_Forward_1_00_X // Play the video at the 1x speed. 619 }).margin(5) 620 Button('rate 2').onClick(() => { 621 this.curRate = PlaybackSpeed.Speed_Forward_2_00_X // Play the video at the 2x speed. 622 }).margin(5) 623 } 624 } 625 }} 626``` 627 628**Reference** 629 630[Video](../reference/arkui-ts/ts-media-components-video.md#start) 631 632## How do I set state-specific styles for a component? 633 634**Solution** 635 636You can use the **stateStyles** attribute to set styles of a component for different states (stateless, pressed, disabled, focused, or clicked). 637 638**Example** 639 640``` 641//xxx.ts 642@Entry 643@Component 644struct StyleExample { 645 @State isEnable: boolean = true; 646 647 @Styles pressedStyles() { 648 .backgroundColor("#ED6F21") 649 .borderRadius(10) 650 .borderStyle(BorderStyle.Dashed) 651 .borderWidth(2) 652 .borderColor('#33000000') 653 .width(120) 654 .height(30) 655 .opacity(1) 656 } 657 build() { 658 Flex({direction: FlexDirection.Column, alignItems: ItemAlign.Center}) { 659 Text("pressed") 660 .backgroundColor('#0A59F7') 661 .borderRadius(20) 662 .borderStyle(BorderStyle.Dotted) 663 .borderWidth(2) 664 .borderColor(Color.Red) 665 .width(100) 666 .height(25) 667 .opacity(1) 668 .fontSize(14) 669 .fontColor(Color.White) 670 .stateStyles({ 671 pressed: this.pressedStyles 672 }) 673 .margin({ 674 bottom: 20 675 }) 676 .textAlign(TextAlign.Center) 677 } 678 .width(350) 679 .height(300) 680 } 681} 682``` 683 684**Reference** 685 686[Polymorphic Style](../reference/arkui-ts/ts-universal-attributes-polymorphic-style.md) 687 688## What should I do if the flex width and height in the \<Scroll> component conflicts with the scrolling? 689 690Applicable to: OpenHarmony 3.2 Beta5 (API version 9, stage model) 691 692**Symptom** 693 694When a container component with a fixed size is added to the **\<Scroll>** component, a scrolling error occurs. 695 696**Solution** 697 698Do not set a size for any container component in the **\<Scroll>** component. In this way, the **\<Scroll>** component can adapt its size to the content. 699 700## What should I do if the height settings in position do not take effect? 701 702Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 703 704**Symptom** 705 706After **position** is set for a container component, the **height** settings do not work. 707 708**Solution** 709 710When **position** is set for a container component, it is taken out of normal flow and works independently from the outer container. In this case, the height does not take effect. You can replace the outer container with a stack to solve this issue. 711 712## Why can't the onBlur or onFocus callback be triggered? 713 714Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 715 716**Solution** 717 718By default, only the Tab button and arrow buttons on the connected keyboard can be used to trigger the focus event. To trigger a focus event by a touch, add the **focusOnTouch** attribute for the target component. 719 720**Reference** 721 722[Focus Control](../reference/arkui-ts/ts-universal-attributes-focus.md) 723 724## How do I disable the scroll event of a \<Grid> nested in the \<Scroll>? 725 726Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 727 728You can use the **onScrollFrameBegin** event and **scrollBy** API to implement nested scrolling of the containers. 729 730For details, see [Nested Scrolling Example](../reference/arkui-ts/ts-container-scroll.md#example-2). 731 732## How do I enable a component to rotate continuously? 733 734Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 735 736You can use [attribute animation](../reference/arkui-ts/ts-animatorproperty.md) to that effect. 737 738## How do I scroll a list with the keyboard? 739 740Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 741 742**Solution** 743 744- Add **focusable\(true\)** to the list item to enable it to obtain focus. 745- Nest a focusable component, for example, **\<Button>**, at the outer layer of each item. 746 747## Why is the click event not triggered for the focused component upon the press of the Enter key after keyboard navigation? 748 749Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 750 751By default, the built-in click event of the component and the custom **onClick** click event are bound to the space bar instead of the Enter key. 752 753## How do I block event bubbling when a button is nested in multi-layer components? 754 755Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 756 757You can bind the button to the **stopPropagation** parameter. 758 759## How do I dynamically create components using code in ArkUI? 760 761Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 762 763**Solution** 764 765ArkUI uses the ArkTS declarative development paradigm. Developers cannot hold component instances. During declaration, you can control component creation by rendering control syntax and dynamically building UI elements. 766 767**Example** 768 769``` 770// Create a component using the if statement. 771if(this.isTrue) { 772 Text ("Create Text Component").fontSize (30) 773} 774// Create a component using the ForEach statement. 775ForEach(this.nums,(item) => { 776 Text(item + '').fontSize(30) 777},item => JSON.stringify(item)) 778``` 779 780**Reference** 781 782[Overview of Rendering Control](../quick-start/arkts-rendering-control-overview.md) 783 784## What is the difference between an @Builder decorated method and a regular method? 785 786Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 787 788**Solution** 789 790The @Builder decorated method allows for use of a custom component, while regular methods do not. If a custom component is used in an @Builder decorated method, it is re-created each time the method is called. 791 792**Reference** 793 794[@BuilderParam](../quick-start/arkts-builderparam.md) 795 796## How do I define @BuilderParam decorated attributes? 797 798Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 799 800**Solution** 801 802- Without parameters 803 804 If no parameter is passed when assigning a value to the **@BuilderParam** decorated attribute (for example, **content: this.specificParam**), define the type of the attribute as a function without a return value (for example, **@BuilderParam content: \(\) =\> void**). 805 806- With parameters 807 808 If any parameter is passed when assigning a value to the **@BuilderParam** decorated attribute (for example, **callContent: this.specificParam1\("111"\)**), define the type of the attribute as **any** (for example, **@BuilderParam callContent: any**). 809 810 811**Reference** 812 813[@BuilderParam](../quick-start/arkts-builderparam.md) 814 815## How do I listen for object changes in an array? 816 817Applicable to: OpenHarmony 3.2 Beta5 (API version 9) 818 819**Solution** 820 821To listen for object changes in an array, use the @Observed and @ObjectLink decorators. **@Observed** applies to classes, and **@ObjectLink** applies to variables. 822 823**Example** 824 8251. Use @Observed on a class. 826 827 ``` 828 @Observed 829 class ClassA { 830 public name: string 831 public c: number 832 public id: number 833 834 constructor(c: number, name: string = 'OK') { 835 this.name = name 836 this.c = c 837 } 838 } 839 ``` 840 8412. Use @ObjectLink on a component variable. 842 843 ``` 844 @Component 845 struct ViewA { 846 label: string = 'ViewA1' 847 @ObjectLink a: ClassA 848 849 build() { 850 Row() { 851 Button(`ViewA [${this.label}] this.a.c= ${this.a.c} +1`) 852 .onClick(() => { 853 this.a.c += 1 854 }) 855 }.margin({ top: 10 }) 856 } 857 } 858 ``` 859 860 861**Reference** 862 863[\@Observed and \@ObjectLink: Observing Attribute Changes in Nested Class Objects](../quick-start/arkts-observed-and-objectlink.md) 864 865## How do I transfer values through the parent component to @Link decorated varaibles in a child component? 866 867Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 868 869**Solution** 870 871To enable a child component to receive the value from the parent component through @Link, '**\$**' must be used to first establish a reference relationship between variables in the child and parent components. 872 873**Example** 874 875The **@Link** semantics are derived from the '**$**' operator. In other words, **$isPlaying** is the two-way binding of the internal state **this.isPlaying**. When the button in the **PlayButton** child component is touched, the value of the @Link decorated variable is changed, and **PlayButton** together with the **\<Image>** and **\<Text>** components of the parent component is refreshed. Similarly, when the button in the parent component is touched, the value of **this.isPlaying** is changed, and **PlayButton** together with the **\<Text>** and **\<Button>** components of the parent component is refreshed. 876 8771. Use the @State decorator in the parent component and use the '**\$**' operator to create a reference for transferring data. 878 879 ``` 880 @Entry 881 @Component 882 struct Player { 883 @State isPlaying: boolean = false 884 build() { 885 Column() { 886 PlayButton({ buttonPlaying: $isPlaying }) 887 Text(`Player is ${this.isPlaying ? '' : 'not'} playing`).fontSize(18) 888 Button('Parent:' + this.isPlaying) 889 .margin(15) 890 .onClick(() => { 891 this.isPlaying = !this.isPlaying 892 }) 893 } 894 } 895 } 896 897 898 ``` 899 9002. Use @Link in the child component to receive data. 901 902 ``` 903 @Component 904 struct PlayButton { 905 @Link buttonPlaying: boolean 906 907 build() { 908 Column() { 909 Button(this.buttonPlaying ? 'pause' : 'play') 910 .margin(20) 911 .onClick(() => { 912 this.buttonPlaying = !this.buttonPlaying 913 }) 914 } 915 } 916 } 917 ``` 918 919 920**Reference** 921 922[@Link](../quick-start/arkts-link.md) 923 924## How does a component synchronize state with its grandchild components? 925 926Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 927 928**Solution** 929 930- Method 1 (recommended): Use the @Provide and @Consume decorators. Specifically, use @Provide in the component and @Consume in the grandchild component to implement two-way data binding between the components. 931 932- Method 2: Use the @State and @Link decorators. Specifically, use @State in the parent component and @Link in each layer of child components (child and grandchild components). 933 934**Example 1** 935 9361. Include a child component in the component. Employ @Provide in the component to provide the **reviewVote** parameter to its grandchild component. 937 938 ``` 939 @Entry 940 @Component 941 struct Father{ 942 @Provide("reviewVote") reviewVotes: number = 0; 943 944 build() { 945 Column() { 946 Son() 947 Button(`Father: ${this.reviewVotes}`) 948 ... 949 } 950 } 951 } 952 ``` 953 9542. Include the grandchild component in the child component. 955 956 ``` 957 @Component 958 struct Son{ 959 build() { 960 Column() { 961 GrandSon() 962 } 963 } 964 } 965 ``` 966 9673. Employ @Consume in the grandchild component to receive the **reviewVote** parameter. 968 969 ``` 970 @Component 971 struct GrandSon{ 972 @Consume("reviewVote") reviewVotes: number 973 974 build() { 975 Column() { 976 Button(`GrandSon: ${this.reviewVotes}`) 977 ... 978 }.width('100%') 979 } 980 } 981 ``` 982 983 984**Example 2** 985 9861. Employ @State in the component **Father** to decorate **reviewVote**. 987 988 ``` 989 @Entry 990 @Component 991 struct Father { 992 @State reviewVotes: number = 0; 993 994 build() { 995 Column() { 996 Son({reviewVotes:$reviewVotes}) 997 Button(`Father: ${this.reviewVotes}`) 998 ... 999 } 1000 } 1001 } 1002 ``` 1003 10042. Employ @Link in the child component **Son** to receive the **reviewVote** parameter passed from **Father**. 1005 1006 ``` 1007 @Component 1008 struct Son{ 1009 @Link reviewVotes: number; 1010 build() { 1011 Column() { 1012 Grandson({reviewVotes:$reviewVotes}) 1013 } 1014 } 1015 } 1016 1017 1018 ``` 1019 10203. Employ @Link in the grandchild component **GrandSon** to receive the **reviewVote** parameter passed from **Son**. 1021 1022 ``` 1023 @Component 1024 struct Grandson{ 1025 @Link reviewVotes: number; 1026 1027 build() { 1028 Column() { 1029 Button(`Grandson: ${this.reviewVotes}`) 1030 ... 1031 }.width('100%') 1032 } 1033 } 1034 ``` 1035 1036 1037## How is a callback function defined in JS? 1038 1039Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 1040 1041**Solution** 1042 1043The following is an example to illustrate how to define a callback function: 1044 10451. Define the callback function. 1046 1047 ``` 1048 // Define a callback function that contains two parameters and returns void. 1049 myCallback: (a:number,b:string) => void 1050 ``` 1051 10522. Initialize the callback function by assigning values. 1053 1054 ``` 1055 aboutToAppear() { 1056 // Initialize the callback function. 1057 this.myCallback= (a,b)=>{ 1058 console.info(`handle myCallback a=${a},b=${b}`) 1059 }} 1060 ``` 1061 1062 1063## How do I maximize performance in cases when a component needs to be updated for multiple times? 1064 1065Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 1066 1067**Solution** 1068 1069Use the state management module for the purpose. Currently, the minimum update is supported. When the data dependency changes, instead of updating the entire custom component, only the view content that depends on the data is updated. 1070 1071## How does this of a function in an object point to the outer layer? 1072 1073Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 1074 1075**Solution** 1076 1077You can use the arrow function for this purpose. 1078 1079**Example** 1080 1081``` 1082const obj = { 1083 start:() => { 1084 return this.num 1085 } 1086} 1087``` 1088 1089## How do I obtain data through an API before page loading? 1090 1091Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 1092 1093**Symptom** 1094 1095Data needs to be obtained before page rendering so as to be rendered when needed. 1096 1097**Solution** 1098 1099In the **aboutToAppear** function, use an asynchronous API to obtain page data and @State to decorate related variables. After the data is obtained, the page is automatically refreshed based on the variables. 1100 1101**Example** 1102 1103``` 1104@Entry 1105@Component 1106struct Test6Page { 1107 // After the data is obtained, the page is automatically refreshed. 1108 @State message: string = 'loading.....' 1109 aboutToAppear(){ 1110 // Simulate an asynchronous API to obtain data. 1111 setTimeout(()=>{ 1112 this.message = 'new msg' 1113 },3000) 1114 } 1115 build() { 1116 Row() { 1117 Column() { 1118 Text(this.message) 1119 .fontSize(50) 1120 .fontWeight(FontWeight.Bold) 1121 } 1122 .width('100%') 1123 } 1124 .height('100%') 1125 } 1126} 1127``` 1128 1129## Can placeholders be configured in the string.json file in the stage model? 1130 1131Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 1132 1133The **string.json** file does not support placeholders. As an alternative, you can define variables on the target page and combine these variables and **Resource** objects. 1134 1135## What are the differences between .ets Files and.ts files? 1136 1137Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 1138 1139**Solution** 1140 1141ArkTS is a superset of TypeScript. In addition to all TS features, ArkTS offers added declarative UI features, allowing you to develop high-performance applications in a more natural and intuitive manner. It is recommended that you use ArtTS for UI development and TS for service logic development. 1142 1143**Reference** 1144 1145[Getting Started with ArkTS](../quick-start/arkts-get-started.md) 1146 1147## How do I send a verification code through email in ArkTS? 1148 1149Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 1150 1151**Solution** 1152 1153To send a verification code, you need to request the server, which in turn calls the SMS verification code API. The SMS service can be used to implement related functions. 1154 1155## How do I display sensor data in the \<Text> component on the UI in real time? 1156 1157Applicable to: OpenHarmony 3.2 Beta5 (API version 9) 1158 1159**Solution** 1160 1161The type of data returned by the sensor is double. To display it in the \<Text> component, first convert the data from double to string. 1162 1163## How do I listen for screen rotation events? 1164 1165Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 1166 1167**Solution** 1168 1169To listen for screen rotation events, use the **mediaquery** API. 1170 1171``` 1172import mediaquery from '@ohos.mediaquery' 1173let listener = mediaquery.matchMediaSync('(orientation: landscape)'); // Listen for landscape events. 1174function onPortrait(mediaQueryResult) { 1175 if (mediaQueryResult.matches) { 1176 // do something here 1177 } else { 1178 // do something here 1179 } 1180} 1181listener.on('change', onPortrait) // Register a callback. 1182listener.off('change', onPortrait) // Deregister a callback. 1183``` 1184 1185**Reference** 1186 1187[@ohos.mediaquery (Media Query)](../reference/apis/js-apis-mediaquery.md) 1188 1189## What should I do if ForEach does not traverse all data after DevEco Studio is updated to the latest version? 1190 1191Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 1192 1193**Solution** 1194 1195In the **forEach\(\)** statement, if the third parameter **keyGenerator** has a value passed in, ensure that the key generated by each element in the data source array is unique. Otherwise, the traversal cannot be performed. If the generated keys are the same, only one key can be generated. 1196 1197The traversal can also be performed if **keyGenerator** is not specified, in which case the system uses the default generation mode. 1198 1199## What should I do if a singleton does not take effect after the page is changed? 1200 1201Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 1202 1203**Symptom** 1204 1205A singleton works only in the same page. It becomes **undefined** when the page changes. 1206 1207**Solution** 1208 1209A JS file is generated for each page, and a defined singleton is generated in each JS file. Therefore, the singleton in applicable only to the owning page. 1210 1211To share an instance across pages, it must be created at the UIAbility or application level. 1212 1213## How do I convert a string in time format to a date object? 1214 1215Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 1216 1217**Solution** 1218 1219If the string is in the yyyy-MM-dd format, you can convert it to a date object by calling **new Date\("yyyy-MM-dd"\)**. 1220 1221``` 1222new Date("2021-05-23"); 1223new Date("2020/2/29"); 1224new Date("2020-14-03"); 1225new Date("14-02-2021"); 1226``` 1227 1228If the string is in other formats, you can convert it to a date object by calling **new Date\(year:number,month:number,day?:number,hour?:number,minute?:number,second?:number,ms?:number\)**. 1229 1230``` 1231Syntax for creating a date based on parameters: 1232new Date(yearValue, IndexOfMonth, dayValue, hours, minutes, seconds) 1233``` 1234 1235Pass the date parameters as arguments. 1236 1237- **yearValue**: the year in the ISO 8061 YYYY format, for example, **2021**. If we specify a value in YY format, it will be incorrectly accepted. For example, the value **21** would be considered the year 1921 rather than 2021. 1238- **IndexOfMonth**: index of the month, which starts from 0. It is obtained by subtracting 1 from the month value. For example, for March, the month value is 3, but the value of **IndexOfMonth** will be 2 (that is, 3 – 1 = 2). The value should typically be within the 0–11 range. 1239- **dayValue**: day of the month. It should range from 1 to 31 depending on the number of days in the month. For example, for 21-05-2021, the day value is **21**. 1240- **hours**: hour of the day. For example, **10** for 10 o'clock. 1241- **minutes**: number of minutes that have elapsed in the hour. 1242- **seconds**: number of seconds past a minute. 1243 1244## How do I convert a string to a byte array in ArkTS? 1245 1246Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 1247 1248**Solution** 1249 1250Refer to the following code: 1251 1252``` 1253stringToArray(str:string) { 1254 var arr = []; 1255 for(var i = 0,j = str.length;i<j;++i) { 1256 arr.push(str.charCodeAt(i)) 1257 } 1258 return arr; 1259} 1260``` 1261 1262## How do I implement string encoding and decoding in ArkTS? 1263 1264Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 1265 1266**Solution** 1267 1268You can use **TextEncoder** and **TextDecoder** provided by the **util** module. 1269 1270**Reference** 1271 1272[TextEncoder](../reference/apis/js-apis-util.md#textencoder), [TextDecoder](../reference/apis/js-apis-util.md#textdecoder) 1273 1274## How do I import and export namespaces? 1275 1276Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 1277 1278**Solution** 1279 1280Use **import** and **export** statements. 1281 1282- Exporting namespaces from the database: 1283 1284 ``` 1285 namespace Util{ 1286 export function getTime(){ 1287 return Date.now() 1288 } 1289 } 1290 export default Util 1291 ``` 1292 1293- Importing namespaces 1294 1295 ``` 1296 import Util from './util' 1297 Util.getTime() 1298 ``` 1299 1300 1301## Can relational database operations be performed in the Worker thread? 1302 1303Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 1304 1305Currently, the relational database (RDB) object in the UI main thread cannot be sent to the Worker thread for operations. To use the RDB in the Worker thread, you must obtain a new RDB object. 1306 1307## How do I obtain files in the resource directory of an application? 1308 1309Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 1310 1311**Solution** 1312 1313- Method 1: Use **\$r** or **\$rawfile**. This method applies to static access, during which the **resource** directory remains unchanged when the application is running. 1314- Method 2: Use **ResourceManager**. This method applies to dynamic access, during which the **resource** directory dynamically changes when the application is running. 1315 1316**Reference** 1317 1318[Resource Categories and Access](../quick-start/resource-categories-and-access.md) and [@ohos.resourceManager (Resource Manager)](../reference/apis/js-apis-resource-manager.md) 1319 1320 1321## How do I convert the XML format to the JSON format? 1322 1323Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 1324 1325**Symptom** 1326 1327The data returned by the server is encoded using Base64 in XML format and needs to be converted to the JSON format for subsequent processing. 1328 1329**Solution** 1330 1331Use the Base64-related APIs in the **util** module to decode data, and then use the **convertxml** module to parse data in XML format. 1332 1333**Example** 1334 1335``` 1336import convertxml from '@ohos.convertxml'; 1337import util from '@ohos.util'; 1338 1339@Entry 1340@Component 1341struct Faq_4_31 { 1342 @State message: string = 'base64 to JSON' 1343 1344 build() { 1345 Row() { 1346 Column() { 1347 Text(this.message) 1348 .fontSize(50) 1349 .fontWeight(FontWeight.Bold) 1350 .onClick(() => { 1351 / *Original data in GBK encoding 1352 <?xml version="1.0" encoding="GBK"?> 1353 <data> 1354 <asset_no>xxxxx</asset_no> 1355 <machine_sn>xxxx</machine_sn> 1356 <bios_id>xxxx</bios_id> 1357 <responsible_emp_name><![CDATA[xxxx]]></responsible_emp_name> 1358 <responsible_account><![CDATA[xxxx xxxx]]></responsible_account> 1359 <responsible_emp_no>xxxx</responsible_emp_no> 1360 <responsible_dept><![CDATA[xxxx]]></responsible_dept> 1361 <user_dept><![CDATA[xxxx]]></user_dept> 1362 <user_name><![CDATA[xxx]]></user_name> 1363 <cur_domain_account>xxxx</cur_domain_account> 1364 <asset_loc><![CDATA[--]]></asset_loc> 1365 <asset_loc_cur><![CDATA[]]></asset_loc_cur> 1366 <asset_type>1</asset_type> 1367 <asset_use>For Outsourcing Staff/xxxx</asset_use> 1368 <overdue_date></overdue_date> 1369 <asset_status>xxxx</asset_status> 1370 <asset_period>xxxx</asset_period> 1371 <license></license> 1372 </data> 1373 */ 1374 let src = 'PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iR0JLIj8+CjxkYXRhPgo8YXNzZXRfbm8+eHh4eHg8L2Fzc2V0X25vPgo8bWFjaGluZV9zbj54eHh4PC9tYWNoaW5lX3NuPgo8Ymlvc19pZD54eHh4PC9iaW9zX2lkPgo8cmVzcG9uc2libGVfZW1wX25hbWU+PCFbQ0RBVEFbeHh4eF1dPjwvcmVzcG9uc2libGVfZW1wX25hbWU+CjxyZXNwb25zaWJsZV9hY2NvdW50PjwhW0NEQVRBW3h4eHggeHh4eF1dPjwvcmVzcG9uc2libGVfYWNjb3VudD4KPHJlc3BvbnNpYmxlX2VtcF9ubz54eHh4PC9yZXNwb25zaWJsZV9lbXBfbm8+CjxyZXNwb25zaWJsZV9kZXB0PjwhW0NEQVRBW3h4eHhdXT48L3Jlc3BvbnNpYmxlX2RlcHQ+Cjx1c2VyX2RlcHQ+PCFbQ0RBVEFbeHh4eF1dPjwvdXNlcl9kZXB0Pgo8dXNlcl9uYW1lPjwhW0NEQVRBW3h4eF1dPjwvdXNlcl9uYW1lPgo8Y3VyX2RvbWFpbl9hY2NvdW50Pnh4eHg8L2N1cl9kb21haW5fYWNjb3VudD4KPGFzc2V0X2xvYz48IVtDREFUQVstLV1dPjwvYXNzZXRfbG9jPgo8YXNzZXRfbG9jX2N1cj48IVtDREFUQVtdXT48L2Fzc2V0X2xvY19jdXI+Cjxhc3NldF90eXBlPjE8L2Fzc2V0X3R5cGU+Cjxhc3NldF91c2U+Rm9yIE91dHNvdXJjaW5nIFN0YWZmL3h4eHg8L2Fzc2V0X3VzZT4KPG92ZXJkdWVfZGF0ZT48L292ZXJkdWVfZGF0ZT4KPGFzc2V0X3N0YXR1cz54eHh4PC9hc3NldF9zdGF0dXM+Cjxhc3NldF9wZXJpb2Q+eHh4eDwvYXNzZXRfcGVyaW9kPgo8bGljZW5zZT48L2xpY2Vuc2U+CjwvZGF0YT4=' 1375 let base64 = new util.Base64Helper(); 1376 // base64 decoding 1377 let src_uint8Array = base64.decodeSync(src); 1378 // Decode the string into a UTF-8 string. 1379 let textDecoder = util.TextDecoder.create("utf-8",{ignoreBOM: true}) 1380 let src_str = textDecoder.decodeWithStream(src_uint8Array) 1381 // Replace the encoding field. 1382 src_str = src_str.replace("GBK","utf-8") 1383 console.log('Test src_str: ' + JSON.stringify(src_str)); 1384 //Convert XML format to JSON format. 1385 let conv = new convertxml.ConvertXML(); 1386 let options = {trim : false, declarationKey:"_declaration", 1387 instructionKey : "_instruction", attributesKey : "_attributes", 1388 textKey : "_text", cdataKey:"_cdata", doctypeKey : "_doctype", 1389 commentKey : "_comment", parentKey : "_parent", typeKey : "_type", 1390 nameKey : "_name", elementsKey : "_elements"} 1391 let src_json = JSON.stringify(conv.convertToJSObject(src_str, options)); 1392 console.log('Test json: ' + JSON.stringify(src_json)); 1393 }) 1394 } 1395 .width('100%') 1396 } 1397 .height('100%') 1398 } 1399} 1400``` 1401 1402## What is the cause of error code 401 obtained through the try/catch statement? 1403 1404Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 1405 1406**Cause** 1407 14081. Mandatory parameters are not passed in. 1409 14102. The parameter type is incorrect. 1411 14123. The parameter is **undefined**. 1413 1414**Reference** 1415 1416[Universal Error Codes](../reference/errorcodes/errorcode-universal.md) 1417