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## Use Scenarios 20 21### Two-Way Binding Between Custom Components 221. 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. 23- The two-way binding syntactic sugar can be considered as: 24 25 ``` 26 Star({ value: this.value, $value: (val: number) => { this.value = val }}) 27 ``` 282. 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. 293. 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. 30 31```ts 32@Entry 33@ComponentV2 34struct Index { 35 @Local value: number = 0; 36 37 build() { 38 Column() { 39 Text(`${this.value}`) 40 Button(`change value`).onClick(() => { 41 this.value++; 42 }) 43 Star({ value: this.value!! }) 44 } 45 } 46} 47 48 49@ComponentV2 50struct Star { 51 @Param value: number = 0; 52 @Event $value: (val: number) => void = (val: number) => {}; 53 54 build() { 55 Column() { 56 Text(`${this.value}`) 57 Button(`change value `).onClick(() => { 58 this.$value(10); 59 }) 60 } 61 } 62} 63``` 64 65 66## Constraints 67- **!!** does not support multi-layer parent-child component transfer. 68- **!!** cannot be used together with @Event. Since API version 18, when **!!** is used to pass parameters to the @Event method of a child component, a compilation error is reported. 69- When three or more exclamation marks (!!!, !!!!, or !!!!!) are used, two-way binding is not supported. 70 71 72### Two-Way Binding Between Built-in Component Parameters 73 74The **!!** 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!!**. 75 76What 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. 77 78#### Rules of Use 79 80- 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. 81 82 | Attribute | Supported Parameter| Initial API Version| 83 | ------------------------------------------------------------ | --------------- | ----------- | 84 | [bindMenu](../reference/apis-arkui/arkui-ts/ts-universal-attributes-menu.md#bindmenu11) | isShow | 13 | 85 | [bindContextMenu](../reference/apis-arkui/arkui-ts/ts-universal-attributes-menu.md#bindcontextmenu12) | isShown | 13 | 86 | [bindPopup](../reference/apis-arkui/arkui-ts/ts-universal-attributes-popup.md#bindpopup) | show | 13 | 87 | [TextInput](../reference/apis-arkui/arkui-ts/ts-basic-components-textinput.md#textinputoptions)| text | 18 | 88 | [TextArea](../reference/apis-arkui/arkui-ts/ts-basic-components-textarea.md#textareaoptions)| text | 18 | 89 | [Search](../reference/apis-arkui/arkui-ts/ts-basic-components-search.md#searchoptions18)| value | 18 | 90 | [BindSheet](../reference/apis-arkui/arkui-ts/ts-universal-attributes-sheet-transition.md) | isShow | 18 | 91 | [BindContentCover](../reference/apis-arkui/arkui-ts/ts-universal-attributes-modal-transition.md) | isShow | 18 | 92 | [Toggle](../reference/apis-arkui/arkui-ts/ts-basic-components-toggle.md#toggleoptions18)| isOn | 18 | 93 | [Checkbox](../reference/apis-arkui/arkui-ts/ts-basic-components-checkbox.md#select) | select | 18 | 94 | [CheckboxGroup](../reference/apis-arkui/arkui-ts/ts-basic-components-checkboxgroup.md#selectall) | selectAll | 18 | 95 | [Radio](../reference/apis-arkui/arkui-ts/ts-basic-components-radio.md#checked) | checked | 18 | 96 | [Rating](../reference/apis-arkui/arkui-ts/ts-basic-components-rating.md#ratingoptions18)| rating | 18 | 97 | [Slider](../reference/apis-arkui/arkui-ts/ts-basic-components-slider.md#slideroptions)| value | 18 | 98 | [Select](../reference/apis-arkui/arkui-ts/ts-basic-components-select.md#selected) | selected | 18 | 99 | [Select](../reference/apis-arkui/arkui-ts/ts-basic-components-select.md#value) | value | 18 | 100 | [MenuItem](../reference/apis-arkui/arkui-ts/ts-basic-components-menuitem.md#selected) | selected | 18 | 101- When the [\@Local](arkts-new-local.md) decorated variable bound to **!!** changes, the UI is rendered synchronously. 102 103 104#### Example 105 106Two-way binding of the **isShow** parameter of the **bindMenu** API: 107 108```ts 109@Entry 110@ComponentV2 111struct BindMenuInterface { 112 @Local isShow: boolean = false; 113 114 build() { 115 Column() { 116 Row() { 117 Text('click show Menu') 118 .bindMenu(this.isShow!!, // Two-way binding. 119 [ 120 { 121 value: 'Menu1', 122 action: () => { 123 console.info('handle Menu1 click'); 124 } 125 }, 126 { 127 value: 'Menu2', 128 action: () => { 129 console.info('handle Menu2 click'); 130 } 131 }, 132 ]) 133 }.height('50%') 134 Text("isShow: " + this.isShow).fontSize(18).fontColor(Color.Red) 135 Row() { 136 Button("Click") 137 .onClick(() => { 138 this.isShow = true; 139 }) 140 .width(100) 141 .fontSize(20) 142 .margin(10) 143 } 144 }.width('100%') 145 } 146} 147``` 148 149 150