!! Syntax: Two-Way Binding
In state management V1, $$ is used for two-way binding of built-in components. In state management V2, the !! syntactic sugar is used to implement two-way binding of components in a unified manner.
NOTE
The !! syntax is supported since API version 12.
Overview
!! is a syntactic sugar used to implement two-way binding of components in initialization of @Param and @Event of the child components. The @Event method name must be declared as "$" + @Param attribute name. For details, see Use Scenarios.
- If the parent component uses !!, the change of the parent component will be synchronized to the child component, and vice versa.
- If the parent component does not use !!, the change of the parent component is unidirectional.
Constraints
- !! does not support multi-layer parent-child component transfer.
Use Scenarios
Two-Way Binding Between Custom Components
- Construct the Star child component in the Index component, bind the value in the parent and child components bidirectionally, and initialize @Param value and @Event $value of the child component.
-
The two-way binding syntactic sugar can be considered as:
Star({ value: this.value, $value: (val: number) => { this.value = val }})
- Click the button in the Index component to change the value, and Text in both the parent component Index and child component Star will be updated.
- Click the button in the child component Star to invoke this.$value(10), and Text in both the parent component Index and child component Star will be updated.
@Entry
@ComponentV2
struct Index {
@Local value: number = 0;
build() {
Column() {
Text(`${this.value}`)
Button(`change value`).onClick(() => {
this.value++;
})
Star({ value: this.value!! })
}
}
}
@ComponentV2
struct Star {
@Param value: number = 0;
@Event $value: (val: number) => void = (val: number) => {};
build() {
Column() {
Text(`${this.value}`)
Button(`change value `).onClick(() => {
this.$value(10);
})
}
}
}
Two-Way Binding Between Built-in Component Parameters
The !! operator provides a TypeScript variable by-reference to a built-in component so that the variable value and the internal state of that component are kept in sync. Add this operator after the variable name, for example, isShow!!.
What the internal state is depends on the component. For example, the isShow parameter of the bindMenu component.
Rules of Use
-
Currently, !! supports two-way binding of the following parameters of the basic types, that is, the parameters can synchronize the current menu or popup state. In addition, !! supports two-way binding of variables of the basic types as well. When a variable is decorated by @Local of V2 or @State of V1, the change of the variable value triggers the UI re-render.
Attribute Supported Parameter Initial API Version bindMenu isShow 13 bindContextMenu isShown 13 bindPopup show 13 -
When the @Local decorated variable bound to !! changes, the UI is rendered synchronously.
Example
Two-way binding of the isShow parameter of the bindMenu API:
@Entry
@ComponentV2
struct BindMenuInterface {
@Local isShow: boolean = false;
build() {
Column() {
Row() {
Text('click show Menu')
.bindMenu(this.isShow!!, // Two-way binding.
[
{
value: 'Menu1',
action: () => {
console.info('handle Menu1 click');
}
},
{
value: 'Menu2',
action: () => {
console.info('handle Menu2 click');
}
},
])
}.height('50%')
Text("isShow: " + this.isShow).fontSize(18).fontColor(Color.Red)
Row() {
Button("Click")
.onClick(() => {
this.isShow = true;
})
.width(100)
.fontSize(20)
.margin(10)
}
}.width('100%')
}
}
