1# Attribute Modifier 2 3With the attribute modifier, you can dynamically set component attributes, complete with the **if/else** syntax and polymorphic style. 4 5> **NOTE** 6> 7> This feature is supported since API version 11. Updates will be marked with a superscript to indicate their earliest API version. 8> 9> Ensure that the attributes set in **attributeModifier** are different from those set in other methods. Otherwise, **attributeModifier** does not take effect when the page is refreshed. 10> 11> **attributeModifier** does not support custom components. 12 13## attributeModifier 14 15attributeModifier(modifier: AttributeModifier\<T>) 16 17Creates an attribute modifier. 18 19**Atomic service API**: This API can be used in atomic services since API version 12. 20 21**System capability**: SystemCapability.ArkUI.ArkUI.Full 22 23**Parameters** 24 25| Name | Type | Mandatory| Description | 26| -------- | -------------------------------------------- | ---- | -------------------------------------------------------------------------------------------------------------------------------- | 27| modifier | [AttributeModifier\<T>](#attributemodifiert) | Yes | Modifier for dynamically setting attributes on the current component. The **if/else** syntax is supported.<br>**modifier**: attribute modifier. You need a custom class to implement the **AttributeModifier** API.| 28 29## AttributeModifier\<T> 30 31You need a custom class to implement the **AttributeModifier** API. 32 33**Atomic service API**: This API can be used in atomic services since API version 12. 34 35**System capability**: SystemCapability.ArkUI.ArkUI.Full 36 37### applyNormalAttribute 38applyNormalAttribute(instance: T) : void 39 40Applies the style of a component in the normal state. 41 42**Atomic service API**: This API can be used in atomic services since API version 12. 43 44**System capability**: SystemCapability.ArkUI.ArkUI.Full 45 46### applyPressedAttribute 47applyPressedAttribute(instance: T) : void 48 49Applies the style of a component in the pressed state. 50 51**Atomic service API**: This API can be used in atomic services since API version 12. 52 53**System capability**: SystemCapability.ArkUI.ArkUI.Full 54 55### applyFocusedAttribute 56applyFocusedAttribute(instance: T) : void 57 58Applies the style of a component in the focused state. 59 60**Atomic service API**: This API can be used in atomic services since API version 12. 61 62**System capability**: SystemCapability.ArkUI.ArkUI.Full 63 64### applyDisabledAttribute 65applyDisabledAttribute(instance: T) : void 66 67Applies the style of a component in the disabled state. 68 69**Atomic service API**: This API can be used in atomic services since API version 12. 70 71**System capability**: SystemCapability.ArkUI.ArkUI.Full 72 73### applySelectedAttribute 74applySelectedAttribute(instance: T) : void 75 76Applies the style of a component in the selected state. 77 78In the preceding APIs, **instance** indicates the component type. You can customize these APIs and use them with the **if/else **syntax. 79 80**Atomic service API**: This API can be used in atomic services since API version 12. 81 82**System capability**: SystemCapability.ArkUI.ArkUI.Full 83 84**Parameters** 85 86| Name | Description | 87| -------- | ------------------------------------------------------------------------------------------------------------ | 88| instance | Component attribute class, which identifies the type of component to which attributes will be applied, for example, **ButtonAttribute** for the **Button** component and **TextAttribute** for the **Text** component.| 89 90**Value range of the instance parameter** 91 92AlphabetIndexerAttribute, BadgeAttribute, BlankAttribute, ButtonAttribute, CalendarPickerAttribute, CanvasAttribute, CheckboxAttribute, CheckboxGroupAttribute, CircleAttribute, ColumnAttribute, ColumnSplitAttribute, ShapeAttribute, CommonAttribute, CounterAttribute, DataPanelAttribute, DatePickerAttribute, DividerAttribute, EllipseAttribute, FlexAttribute, FlowItemAttribute, FormLinkAttribute, GaugeAttribute, GridAttribute, GridColAttribute, ColumnAttribute, GridItemAttribute, GridRowAttribute, HyperlinkAttribute, ImageAttribute, ImageAnimatorAttribute, ImageSpanAttribute, LineAttribute, ListAttribute, ListItemAttribute, ListItemGroupAttribute, LoadingProgressAttribute, MarqueeAttribute, MenuAttribute, MenuItemAttribute, MenuItemGroupAttribute, NavDestinationAttribute, NavigationAttribute, NavigatorAttribute, NavRouterAttribute, PanelAttribute, PathAttribute, PatternLockAttribute, PolygonAttribute, PolylineAttribute, ProgressAttribute, QRCodeAttribute, RadioAttribute, RatingAttribute, RectAttribute, RefreshAttribute, RelativeContainerAttribute, RichEditorAttribute, RichTextAttribute, RowAttribute, RowSplitAttribute, ScrollAttribute, ScrollBarAttribute, SearchAttribute, SelectAttribute, ShapeAttribute, SideBarContainerAttribute, SliderAttribute, SpanAttribute, StackAttribute, StepperAttribute, StepperItemAttribute, SwiperAttribute, SymbolGlyphAttribute, TabContentAttribute, TabsAttribute, TextAttribute, TextAreaAttribute, TextClockAttribute, TextInputAttribute, TextPickerAttribute, TextTimerAttribute, TimePickerAttribute, ToggleAttribute, VideoAttribute, WaterFlowAttribute, XComponentAttribute, ParticleAttribute<!--Del-->, EffectComponentAttribute, FormComponentAttribute, PluginComponentAttribute, RemoteWindowAttribute, UIExtensionComponentAttribute<!--DelEnd--> 93 94**Supported attributes** 95 961. Attributes that accept or return a [CustomBuilder](ts-types.md#custombuilder8) are not supported. 972. Attributes that accept a [modifier](../../../ui/arkts-user-defined-modifier.md) type, such as [attributeModifier](#attributemodifier), [drawModifier](./ts-universal-attributes-draw-modifier.md), and [gestureModifier](./ts-universal-attributes-gesture-modifier.md), are not supported. 983. Attribute related to [animation](./ts-animatorproperty.md) are not supported. 994. Attributes of the [gesture](../../../ui/arkts-gesture-events-binding.md) type are not supported. 1005. Attribute related to [stateStyles](./ts-universal-attributes-polymorphic-style.md) are not supported. 1016. Deprecated attributes are not supported. 102<!--Del--> 1037. Built-in component attributes are not supported.<!--DelEnd--> 104 105When unsupported or unimplemented attributes are used, exceptions such as "Method not implemented." or "is not callable" are thrown. The specific scope of supported attributes is the same as the base class attribute API. For details, see [Supported Scope of Attributes](#supported-scope-of-attributes). 106 107## Custom Modifier 108Custom modifiers can be used in building components and configuring attributes since API version 12. Through the custom modifiers, you can call the attribute and style APIs of encapsulated components. 109 110**Supported custom modifiers** 111 112CommonModifier, ColumnModifier, ColumnSplitModifier, RowModifier, RowSplitModifier, SideBarContainerModifier, BlankModifier, DividerModifier, GridColModifier, GridRowModifier, NavDestinationModifier, NavigatorModifier, StackModifier, NavigationModifier, NavRouterModifier, StepperItemModifier, TabsModifier, GridModifier, GridItemModifier, ListModifier, ListItemModifier, ListItemGroupModifier, ScrollModifier, SwiperModifier, WaterFlowModifier, ButtonModifier, CounterModifier, TextPickerModifier, TimePickerModifier, ToggleModifier, CalendarPickerModifier, CheckboxModifier, CheckboxGroupModifier, DatePickerModifier, RadioModifier, RatingModifier, SelectModifier, SliderModifier, PatternLockModifier, SpanModifier, RichEditorModifier, RefreshModifier, SearchModifier, TextAreaModifier, TextModifier, TextInputModifier, ImageSpanModifier, ImageAnimatorModifier, ImageModifier, VideoModifier, DataPanelModifier, GaugeModifier, LoadingProgressModifier, MarqueeModifier, ProgressModifier, QRCodeModifier, TextClockModifier, TextTimerModifier, LineModifier, PathModifier, PolygonModifier, PolylineModifier, RectModifier, ShapeModifier, AlphabetIndexerModifier, FormComponentModifier, HyperlinkModifier, MenuModifier, MenuItemModifier, PanelModifier, SymbolGlyphModifier, ParticleModifier 113**CommonModifier** can be used for unexposed components. 114 115**Precautions** 1161. When a custom modifier is applied to a component, the corresponding attribute of the component takes effect. 1172. Updating the attribute value of a custom modifier changes the corresponding attribute of the component to which the modifier is applied. The custom modifier is a base class, and the constructed object is a child class object. When using the object, use **as** to assert the type as a child class. 1183. With a custom modifier applied to two components, updating the attribute value of the custom modifier changes the corresponding attributes of both components. 1194. If attributes A and B are set through a custom modifier, and then attributes C and D are set through other means, all the four attributes take effect on the component. 1205. The custom modifier does not support change observation for @State decorated variables. For details, see Example 2. 1216. If you use **attributeModifier** to set attributes multiple times, all the set attributes take effect, and those attributes that are set multiple times take effect based on the configuration sequence. 122 123## Example 124### Example 1: Switching the Background Color with a Modifier 125 126This example demonstrates how to switch the background color of a **Button** component by binding it to a modifier. 127 128```ts 129// xxx.ets 130class MyButtonModifier implements AttributeModifier<ButtonAttribute> { 131 isDark: boolean = false 132 133 applyNormalAttribute(instance: ButtonAttribute): void { 134 if (this.isDark) { 135 instance.backgroundColor(Color.Black) 136 } else { 137 instance.backgroundColor(Color.Red) 138 } 139 } 140} 141 142@Entry 143@Component 144struct attributeDemo { 145 @State modifier: MyButtonModifier = new MyButtonModifier() 146 147 build() { 148 Row() { 149 Column() { 150 Button("Button") 151 .attributeModifier(this.modifier) 152 .onClick(() => { 153 this.modifier.isDark = !this.modifier.isDark 154 }) 155 } 156 .width('100%') 157 } 158 .height('100%') 159 } 160} 161``` 162 163 164### Example 2: Implementing the Pressed State Effect with a Modifier 165 166This example demonstrates how to implement a pressed state effect for a **Button** component by binding it to a modifier. For details about how to use the attribute modifier with state management V2, see [Modifier and makeObserved](../../../quick-start/arkts-v1-v2-migration.md#modifier). 167 168```ts 169// xxx.ets 170class MyButtonModifier implements AttributeModifier<ButtonAttribute> { 171 applyNormalAttribute(instance: ButtonAttribute): void { 172 instance.backgroundColor(Color.Black) 173 } 174 175 applyPressedAttribute(instance: ButtonAttribute): void { 176 instance.backgroundColor(Color.Red) 177 } 178} 179 180@Entry 181@Component 182struct attributePressedDemo { 183 @State modifier: MyButtonModifier = new MyButtonModifier() 184 185 build() { 186 Row() { 187 Column() { 188 Button("Button") 189 .attributeModifier(this.modifier) 190 } 191 .width('100%') 192 } 193 .height('100%') 194 } 195} 196``` 197 198 199### Example 3: Understanding Custom Modifiers Do Not Support State Data Changes 200 201This example shows how to set the width of a custom modifier using state data. Custom modifiers do not support observing changes in data decorated with the @State decorator. Therefore, the width does not change when the button is clicked. 202 203```ts 204import { CommonModifier } from "@kit.ArkUI" 205 206const TEST_TAG : string = "AttributeModifier"; 207class MyModifier extends CommonModifier { 208 applyNormalAttribute(instance: CommonAttribute): void { 209 super.applyNormalAttribute?.(instance); 210 } 211} 212 213@Component 214struct MyImage1 { 215 @Link modifier: CommonModifier 216 217 build() { 218 Image($r("app.media.startIcon")).attributeModifier(this.modifier as MyModifier) 219 } 220} 221 222@Entry 223@Component 224struct Index { 225 index: number = 0; 226 @State width1: number = 100; 227 @State height1: number = 100; 228 @State myModifier: CommonModifier = new MyModifier().width(this.width1).height(this.height1).margin(10) 229 230 build() { 231 Column() { 232 Button($r("app.string.EntryAbility_label")) 233 .margin(10) 234 .onClick(() => { 235 console.log(TEST_TAG, "onClick") 236 this.index++; 237 if (this.index % 2 === 1) { 238 this.width1 = 10; 239 console.log(TEST_TAG, "setGroup1") 240 } else { 241 this.width1 = 10; 242 console.log(TEST_TAG, "setGroup2") 243 } 244 }) 245 MyImage1({ modifier: this.myModifier }) 246 } 247 .width('100%') 248 } 249} 250``` 251 252 253### Example 4: Combining Modifier and Custom Modifier Attributes 254 255In this example, the custom modifier sets the **width** and **height** attributes, and the **borderStyle** and **borderWidth** attributes are set through a button click. In this case, all the four attributes take effect when the button is clicked. 256 257```ts 258import { CommonModifier } from "@kit.ArkUI" 259 260const TEST_TAG: string = "AttributeModifier"; 261 262class MyModifier extends CommonModifier { 263 applyNormalAttribute(instance: CommonAttribute): void { 264 super.applyNormalAttribute?.(instance); 265 } 266 267 public setGroup1(): void { 268 this.borderStyle(BorderStyle.Dotted) 269 this.borderWidth(8) 270 } 271 272 public setGroup2(): void { 273 this.borderStyle(BorderStyle.Dashed) 274 this.borderWidth(8) 275 } 276} 277 278@Component 279struct MyImage1 { 280 @Link modifier: CommonModifier 281 282 build() { 283 Image($r("app.media.startIcon")).attributeModifier(this.modifier as MyModifier) 284 } 285} 286 287@Entry 288@Component 289struct Index { 290 @State myModifier: CommonModifier = new MyModifier().width(100).height(100).margin(10) 291 index: number = 0; 292 293 build() { 294 Column() { 295 Button($r("app.string.EntryAbility_label")) 296 .margin(10) 297 .onClick(() => { 298 console.log(TEST_TAG, "onClick") 299 this.index++; 300 if (this.index % 2 === 1) { 301 (this.myModifier as MyModifier).setGroup1() 302 console.log(TEST_TAG, "setGroup1") 303 } else { 304 (this.myModifier as MyModifier).setGroup2() 305 console.log(TEST_TAG, "setGroup2") 306 } 307 }) 308 MyImage1({ modifier: this.myModifier }) 309 } 310 .width('100%') 311 } 312} 313``` 314 315 316## Supported Scope of Attributes 317 318Attributes not listed in the table below are supported by default. 319 320**Table 1** Unsupported attributes in the CommonAttribute API 321 322| Attribute | Supported/Unsupported| Error Message | Remarks | 323| ------------------------ | -------- | ------------------------- | ----------------------------------------- | 324| accessibilityChecked | Not supported | is not callable | - | 325| accessibilitySelected | Not supported | is not callable | - | 326| accessibilityTextHint | Not supported | is not callable | - | 327| accessibilityVirtualNode | Not supported | is not callable | Attributes that accept a CustomBuilder are not supported. | 328| animation | Not supported | Method not implemented. | Animation-related attributes are not supported. | 329| attributeModifier | Not supported | - | **attributeModifier** does not take effect when nested.| 330| background | Not supported | Method not implemented. | Attributes that accept a CustomBuilder are not supported. | 331| backgroundFilter | Not supported | is not callable | - | 332| bindContentCover | Not supported | Method not implemented. | Attributes that accept a CustomBuilder are not supported. | 333| bindContextMenu | Not supported | Method not implemented. | Attributes that accept a CustomBuilder are not supported. | 334| bindMenu | Not supported | Method not implemented. | Attributes that accept a CustomBuilder are not supported. | 335| bindPopup | Not supported | Method not implemented. | Attributes that accept a CustomBuilder are not supported. | 336| bindSheet | Not supported | Method not implemented. | Attributes that accept a CustomBuilder are not supported. | 337| chainWeight | Not supported | is not callable | - | 338| compositingFilter | Not supported | is not callable | - | 339| drawModifier | Not supported | is not callable | Modifier-related attributes are not supported. | 340| foregroundFilter | Not supported | is not callable | - | 341| freeze | Not supported | is not callable | - | 342| gesture | Not supported | Method not implemented. | Gesture-related attributes are not supported. | 343| gestureModifier | Not supported | is not callable | Modifier-related attributes are not supported. | 344| onAccessibilityHover | Not supported | is not callable | - | 345| onChildTouchTest | Not supported | is not callable | - | 346| onKeyEventDispatch | Not supported | is not callable | - | 347| onPreDrag | Not supported | Method not implemented. | - | 348| onTouchIntercept | Not supported | is not callable | - | 349| onVisibleAreaChange | Not supported | Method not implemented. | - | 350| parallelGesture | Not supported | Method not implemented. | Gesture-related attributes are not supported. | 351| priorityGesture | Not supported | Method not implemented. | Gesture-related attributes are not supported. | 352| reuseId | Not supported | Method not implemented. | - | 353| safeAreaPadding | Not supported | is not callable | - | 354| stateStyles | Not supported | Method not implemented. | **stateStyles**-related attributes are not supported. | 355| useSizeType | Not supported | Method not implemented. | Deprecated attributes are not supported. | 356| visualEffect | Not supported | is not callable | - | 357| accessibilityDescription | Partially supported | - | Attributes that accept a **Resource** object are not supported. | 358| accessibilityText | Partially supported | - | Attributes that accept a **Resource** object are not supported. | 359| dragPreview | Partially supported | Builder is not supported. | Attributes that accept a CustomBuilder are not supported. | 360