Problem Description
In the @ComponentV2 component, data cannot be directly passed to the @CustomDialog component.
The problematic code is as follows:
@ComponentV2
export struct Page {
@Local selectIndex: number = 0;
dialogController: CustomDialogController | null = new CustomDialogController({
builder: AccountSafeDialog({
selectIndex:this.selectIndex,
}),
})
// ...
}
// Define pop-up window
@CustomDialog
export struct AccountSafeDialog {
controller?: CustomDialogController;
@Link selectIndex: number;
// ...
}
Background Knowledge
- The @ComponentV2 decorator is a custom component decorator used in conjunction with V2 state variables. Variables decorated with the @Link decorator share the same value as the data source in their parent component. The custom dialog CustomDialog is displayed through the CustomDialogController class, and both are only used in state management V1.
- A pop-up window can be implemented by using the Dialog mode of NavDestination. In this case, the entire NavDestination area is transparent by default, with no component occupying the space.
Troubleshooting Process
Running the code results in an error:
error message:undefined 'selectIndex'[-21]
<@Component 'AccountSafeDialog'[375]>:
constructor: source variable in parent/ancestor @Component must be defined. Application error!
The error message indicates that the variable selectIndex cannot be found. In the code, selectIndex is decorated with @Local, which means this variable is passed from the parent component. Upon checking the parent component, it was found to be decorated with @ComponentV2, indicating a different state management version compared to the @CustomDialog decorator used in the child component.
Analysis Conclusion
There is a state management version incompatibility between components decorated with @ComponentV2 and custom dialog components decorated with @CustomDialog, which prevents data from being correctly passed to the custom dialog components decorated with @CustomDialog.
Solution
You can replace @CustomDialog with a Page using @ComponentV2 and implement the pop-up dialog using the DIALOG mode of Navigation.
Example code is as follows:
- In Index.ets, use the
pushPathByNamemethod to push the specified NavDestination page information onto the stack.
@Entry
@ComponentV2
struct NavigationExample {
pageInfos: NavPathStack = new NavPathStack();
@Local selectIndex: number = 10
build() {
Navigation(this.pageInfos) {
Column() {
Button('pushPath', { stateEffect: true, type: ButtonType.Capsule })
.width('80%')
.height(40)
.margin(20)
.onClick(() => {
this.pageInfos.pushPathByName('pageOne', this.selectIndex, () => {
}, false); // Push the NavDestination page information specified by name onto the stack
})
}
}.title('NavIndex')
}
}
2.Create PageOne.ets as a pop-up page and set the mode of NavDestination to DIALOG mode.
@Builder
export function PageOneBuilder(name: string, param: Object) {
PageOne()
}
@ComponentV2
export struct PageOne {
pageInfos: NavPathStack = new NavPathStack();
@Local selectIndex: number = 0
build() {
NavDestination() {
Column() {
Text(this.selectIndex.toString())
}
}
.onReady(context => {
this.selectIndex = context.pathInfo.param as number;
})
.position({ left: 50, top: 200 })
.backgroundColor(Color.Pink)
.width(300)
.height(300)
.mode(NavDestinationMode.DIALOG)
.hideBackButton(true)
}
}
3.In the module.json5 configuration file under the src/main directory, configure the routerMap field in the module section as "routerMap": "$profile:router_map", and add a new router_map.json file in the src/main/resources/base/profile directory. An example of router_map.json is as follows:
{
"routerMap": [
{
"name": "pageOne",
"pageSourceFile": "src/main/ets/pages/PageOne.ets",
"buildFunction": "PageOneBuilder",
"data": {
"description": "this is pageOne"
}
}
]
}
Limitations or Considerations
- This example supports API Version 19 Release and later versions.
- This example supports HarmonyOS 5.1.1 Release SDK and later versions.
- This example requires DevEco Studio 5.1.1 Release or later for building and running.
Top comments (0)