Implementing a Four-Level Address Cascade Component with Custom Dialog in Huawei HarmonyOS (Next)
This tutorial demonstrates how to build a four‑level province‑city‑district‑town address cascade selector using a custom dialog in Huawei HarmonyOS, covering preparation, custom dialog creation, component communication, logic implementation, and data handling with complete code examples.
The article introduces a custom address cascade selector for HarmonyOS (Next) that supports up to four levels (province, city, district, town) and explains why the built‑in TextPicker becomes unwieldy beyond three levels.
Purpose : Learn the core usage of HarmonyOS custom dialogs, understand the implementation idea of cascade selection, and see how to encapsulate and communicate between custom components.
1. Preparation : Install the latest DevEco Studio, create a new project, and add the directory ets/components/cascade/ with files addressObj.ts , index.ets , CustomAddress.ets , and the TypeScript declaration Cascade.d.ts .
2. Custom Dialog : Copy the official custom‑dialog example into ets/components/cascade/index.ets , remove the @Entry decorator, rename the component, and export it. The dialog code is shown below:
// xxx.ets
@CustomDialog
struct CustomDialogExample {
controller?: CustomDialogController
cancel: () => void = () => {}
confirm: () => void = () => {}
build() {
Column() {
Text('这是自定义弹窗').fontSize(30).height(100)
Button('点我关闭弹窗')
.onClick(() => {
if (this.controller != undefined) {
this.controller.close()
}
})
.margin(20)
}
}
}
// @Entry 去掉入口页面标志
@Component
export struct CustomDialogCascade {
dialogController: CustomDialogController | null = new CustomDialogController({
builder: CustomDialogExample({
cancel: () => this.onCancel(),
confirm: () => this.onAccept()
}),
autoCancel: true,
alignment: DialogAlignment.Center,
width: 300,
height: 200,
borderWidth: 1,
borderStyle: BorderStyle.Dashed,
borderColor: Color.Blue,
backgroundColor: Color.White,
shadow: ({ radius: 20, color: Color.Grey, offsetX: 50, offsetY: 0 })
})
aboutToDisappear() { this.dialogController = null }
onCancel() { console.info('Cancel clicked') }
onAccept() { console.info('Confirm clicked') }
build() {
Column() {
Button('click me')
.onClick(() => { if (this.dialogController) this.dialogController.open() })
.backgroundColor(0x317aff)
}.width('100%').margin({ top: 5 })
}
}Update ets/pages/index.ets to import and use the custom component.
import {CustomDialogCascade} from "../components/cascade/index"
@Entry
@Component
struct Index {
build() {
RelativeContainer() { CustomDialogCascade() }
.height('100%').width('100%')
}
}3. Component Communication : The article explains HarmonyOS state decorators ( @State , @Prop , @Link , @Provide , @Consume , @Watch ) and how they affect data flow between parent and child components.
4. Logic Completion : Demonstrates how the parent component can trigger the child dialog, pass the desired address level, and receive the selected address data via callbacks.
Key code for passing parameters and handling callbacks:
import {CustomDialogCascade} from "../components/cascade/index"
@Entry
@Component
struct Index {
@State CustomDialogController: CustomDialogController | null = null
build() {
Column() {
Button('打开弹窗')
.onClick(() => { this.CustomDialogController?.open() })
CustomDialogCascade({
level: 3,
CustomDialogController: this.CustomDialogController,
confirm: (data) => { console.log('data', data) }
})
}.height('100%').width('100%')
}
}5. Address Cascade Logic : Stores address data in addressObj.ts as a nested object, defines types in Cascade.d.ts , and implements the core UI in CustomAddress.ets . The component loads region data based on the selected parent code, updates steps, and returns the final selection.
import { regionDict } from "./addressObj"
import { RegionType, levelNumber } from './Cascade'
@CustomDialog
export struct CustomAddress {
@State region: RegionType[] = []
@State data: RegionType[] = []
@State step: number = 0
@State active: number = 0
level: levelNumber = 4
// ... (methods loadRegionData, onStepClickSelect, onRowClickSelect, getLableName)
build() {
Column() {
// UI for selected steps and list of regions
}
}
}Finally, the article wraps up by confirming that the custom dialog closes automatically after a town is selected and the selected address data is printed in the parent component.
Conclusion : The guide provides a complete walkthrough for creating a reusable, four‑level address cascade selector with a custom dialog in HarmonyOS, illustrating component encapsulation, state management, and parent‑child communication.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.