1# !! Syntax: Two-Way Binding
2In state management V1, [$$](./arkts-two-way-sync.md) is used for two-way binding of built-in components.
3In state management V2, the **!!** syntactic sugar is used to implement two-way binding of components in a unified manner.
4
5
6>**NOTE**
7>
8>The **!!** syntax is supported since API version 12.
9>
10
11## Overview
12
13**!!** 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](#use-scenarios).
14
15- If the parent component uses **!!**, the change of the parent component will be synchronized to the child component, and vice versa.
16- If the parent component does not use **!!**, the change of the parent component is unidirectional.
17
18
19## Constraints
20**!!** does not support multi-layer parent-child component transfer.
21
22
23## Use Scenarios
24
25### Two-Way Binding Between Custom Components
261. 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.
27- The two-way binding syntactic sugar can be considered as:
28
29    ```
30    Star({ value: this.value, $value: (val: number) => { this.value = val }})
31    ```
322. 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.
333. 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.
34
35```ts
36@Entry
37@ComponentV2
38struct Index {
39  @Local value: number = 0;
40
41  build() {
42    Column() {
43      Text(`${this.value}`)
44      Button(`change value`).onClick(() => {
45        this.value++;
46      })
47      Star({ value: this.value!! })
48    }
49  }
50}
51
52
53@ComponentV2
54struct Star {
55  @Param value: number = 0;
56  @Event $value: (val: number) => void = (val: number) => {};
57
58  build() {
59    Column() {
60      Text(`${this.value}`)
61      Button(`change value `).onClick(() => {
62        this.$value(10);
63      })
64    }
65  }
66}
67```
68
69
70### Two-Way Binding Between Built-in Component Parameters
71
72The **!!** 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!!**.
73
74What the internal state is depends on the component. For example, the **isShow** parameter of the [bindMenu](../reference/apis-arkui/arkui-ts/ts-universal-attributes-menu.md) component.
75
76#### Rules of Use
77
78- 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](arkts-new-local.md) of V2 or [\@State](arkts-state.md) of V1, the change of the variable value triggers the UI re-render.
79
80  | Attribute                                                        | Supported Parameter| Initial API Version|
81  | ------------------------------------------------------------ | --------------- | ----------- |
82  | [bindMenu](../reference/apis-arkui/arkui-ts/ts-universal-attributes-menu.md#bindmenu11) | isShow | 13          |
83  | [bindContextMenu](../reference/apis-arkui/arkui-ts/ts-universal-attributes-menu.md#bindcontextmenu12) | isShown | 13          |
84  | [bindPopup](../reference/apis-arkui/arkui-ts/ts-universal-attributes-popup.md#bindpopup) | show | 13   |
85
86- When the [\@Local](arkts-new-local.md) decorated variable bound to **!!** changes, the UI is rendered synchronously.
87
88
89#### Example
90
91Two-way binding of the **isShow** parameter of the **bindMenu** API:
92
93```ts
94@Entry
95@ComponentV2
96struct BindMenuInterface {
97  @Local isShow: boolean = false;
98
99  build() {
100    Column() {
101      Row() {
102        Text('click show Menu')
103          .bindMenu(this.isShow!!, // Two-way binding.
104            [
105              {
106                value: 'Menu1',
107                action: () => {
108                  console.info('handle Menu1 click');
109                }
110              },
111              {
112                value: 'Menu2',
113                action: () => {
114                  console.info('handle Menu2 click');
115                }
116              },
117            ])
118      }.height('50%')
119      Text("isShow: " + this.isShow).fontSize(18).fontColor(Color.Red)
120      Row() {
121        Button("Click")
122          .onClick(() => {
123            this.isShow = true;
124          })
125          .width(100)
126          .fontSize(20)
127          .margin(10)
128      }
129    }.width('100%')
130  }
131}
132```
133
134![bindMenu](figures/bindmenu_doublebind.gif)
135