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> **NOTE** 38> 39> In the following APIs, setting the same value or object for the same attribute of the **instance** object will not trigger an update. 40 41### applyNormalAttribute 42applyNormalAttribute(instance: T) : void 43 44Applies the style of a component in the normal state. 45 46**Atomic service API**: This API can be used in atomic services since API version 12. 47 48**System capability**: SystemCapability.ArkUI.ArkUI.Full 49 50### applyPressedAttribute 51applyPressedAttribute(instance: T) : void 52 53Applies the style of a component in the pressed state. 54 55**Atomic service API**: This API can be used in atomic services since API version 12. 56 57**System capability**: SystemCapability.ArkUI.ArkUI.Full 58 59### applyFocusedAttribute 60applyFocusedAttribute(instance: T) : void 61 62Applies the style of a component in the focused state. 63 64**Atomic service API**: This API can be used in atomic services since API version 12. 65 66**System capability**: SystemCapability.ArkUI.ArkUI.Full 67 68### applyDisabledAttribute 69applyDisabledAttribute(instance: T) : void 70 71Applies the style of a component in the disabled state. 72 73**Atomic service API**: This API can be used in atomic services since API version 12. 74 75**System capability**: SystemCapability.ArkUI.ArkUI.Full 76 77### applySelectedAttribute 78applySelectedAttribute(instance: T) : void 79 80Applies the style of a component in the selected state. 81 82In the preceding APIs, **instance** indicates the component type. You can customize these APIs and use them with the **if/else **syntax. 83 84**Atomic service API**: This API can be used in atomic services since API version 12. 85 86**System capability**: SystemCapability.ArkUI.ArkUI.Full 87 88**Parameters** 89 90| Name | Description | 91| -------- | ------------------------------------------------------------------------------------------------------------ | 92| 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.| 93 94**Value range of the instance parameter** 95 96AlphabetIndexerAttribute, 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--> 97 98**Supported attributes** 99 1001. Attributes that accept or return a [CustomBuilder](ts-types.md#custombuilder8) are not supported. 1012. 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. 1023. Attribute related to [animation](./ts-animatorproperty.md) are not supported. 1034. Attributes of the [gesture](../../../ui/arkts-gesture-events-binding.md) type are not supported. 1045. Attribute related to [stateStyles](./ts-universal-attributes-polymorphic-style.md) are not supported. 1056. Deprecated attributes are not supported. 106<!--Del--> 1077. Built-in component attributes are not supported.<!--DelEnd--> 108 109When unsupported or unimplemented attributes are used, exceptions such as "Method not implemented.", "is not callable", or "Builder is not supported." 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). 110 111## Custom Modifier 112Custom 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. 113 114**Supported custom modifiers** 115 116CommonModifier, 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 117**CommonModifier** can be used for unexposed components. 118 119**Precautions** 1201. When a custom modifier is applied to a component, the corresponding attribute of the component takes effect. 1212. 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. 1223. With a custom modifier applied to two components, updating the attribute value of the custom modifier changes the corresponding attributes of both components. 1234. 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. 1245. The custom modifier does not support change observation for @State decorated variables. For details, see Example 2. 1256. 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. 126 127## Example 128### Example 1: Switching the Background Color with a Modifier 129 130This example demonstrates how to switch the background color of a **Button** component by binding it to a modifier. 131 132```ts 133// xxx.ets 134class MyButtonModifier implements AttributeModifier<ButtonAttribute> { 135 isDark: boolean = false 136 137 applyNormalAttribute(instance: ButtonAttribute): void { 138 if (this.isDark) { 139 instance.backgroundColor(Color.Black) 140 } else { 141 instance.backgroundColor(Color.Red) 142 } 143 } 144} 145 146@Entry 147@Component 148struct attributeDemo { 149 @State modifier: MyButtonModifier = new MyButtonModifier() 150 151 build() { 152 Row() { 153 Column() { 154 Button("Button") 155 .attributeModifier(this.modifier) 156 .onClick(() => { 157 this.modifier.isDark = !this.modifier.isDark 158 }) 159 } 160 .width('100%') 161 } 162 .height('100%') 163 } 164} 165``` 166 167 168### Example 2: Implementing the Pressed State Effect with a Modifier 169 170This 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). 171 172```ts 173// xxx.ets 174class MyButtonModifier implements AttributeModifier<ButtonAttribute> { 175 applyNormalAttribute(instance: ButtonAttribute): void { 176 instance.backgroundColor(Color.Black) 177 } 178 179 applyPressedAttribute(instance: ButtonAttribute): void { 180 instance.backgroundColor(Color.Red) 181 } 182} 183 184@Entry 185@Component 186struct attributePressedDemo { 187 @State modifier: MyButtonModifier = new MyButtonModifier() 188 189 build() { 190 Row() { 191 Column() { 192 Button("Button") 193 .attributeModifier(this.modifier) 194 } 195 .width('100%') 196 } 197 .height('100%') 198 } 199} 200``` 201 202 203### Example 3: Understanding Custom Modifiers Do Not Support State Data Changes 204 205This 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. 206 207```ts 208import { CommonModifier } from "@kit.ArkUI" 209 210const TEST_TAG : string = "AttributeModifier"; 211class MyModifier extends CommonModifier { 212 applyNormalAttribute(instance: CommonAttribute): void { 213 super.applyNormalAttribute?.(instance); 214 } 215} 216 217@Component 218struct MyImage1 { 219 @Link modifier: CommonModifier 220 221 build() { 222 Image($r("app.media.startIcon")).attributeModifier(this.modifier as MyModifier) 223 } 224} 225 226@Entry 227@Component 228struct Index { 229 index: number = 0; 230 @State width1: number = 100; 231 @State height1: number = 100; 232 @State myModifier: CommonModifier = new MyModifier().width(this.width1).height(this.height1).margin(10) 233 234 build() { 235 Column() { 236 Button($r("app.string.EntryAbility_label")) 237 .margin(10) 238 .onClick(() => { 239 console.log(TEST_TAG, "onClick") 240 this.index++; 241 if (this.index % 2 === 1) { 242 this.width1 = 10; 243 console.log(TEST_TAG, "setGroup1") 244 } else { 245 this.width1 = 10; 246 console.log(TEST_TAG, "setGroup2") 247 } 248 }) 249 MyImage1({ modifier: this.myModifier }) 250 } 251 .width('100%') 252 } 253} 254``` 255 256 257### Example 4: Combining Modifier and Custom Modifier Attributes 258 259In 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. 260 261```ts 262import { CommonModifier } from "@kit.ArkUI" 263 264const TEST_TAG: string = "AttributeModifier"; 265 266class MyModifier extends CommonModifier { 267 applyNormalAttribute(instance: CommonAttribute): void { 268 super.applyNormalAttribute?.(instance); 269 } 270 271 public setGroup1(): void { 272 this.borderStyle(BorderStyle.Dotted) 273 this.borderWidth(8) 274 } 275 276 public setGroup2(): void { 277 this.borderStyle(BorderStyle.Dashed) 278 this.borderWidth(8) 279 } 280} 281 282@Component 283struct MyImage1 { 284 @Link modifier: CommonModifier 285 286 build() { 287 Image($r("app.media.startIcon")).attributeModifier(this.modifier as MyModifier) 288 } 289} 290 291@Entry 292@Component 293struct Index { 294 @State myModifier: CommonModifier = new MyModifier().width(100).height(100).margin(10) 295 index: number = 0; 296 297 build() { 298 Column() { 299 Button($r("app.string.EntryAbility_label")) 300 .margin(10) 301 .onClick(() => { 302 console.log(TEST_TAG, "onClick") 303 this.index++; 304 if (this.index % 2 === 1) { 305 (this.myModifier as MyModifier).setGroup1() 306 console.log(TEST_TAG, "setGroup1") 307 } else { 308 (this.myModifier as MyModifier).setGroup2() 309 console.log(TEST_TAG, "setGroup2") 310 } 311 }) 312 MyImage1({ modifier: this.myModifier }) 313 } 314 .width('100%') 315 } 316} 317``` 318 319 320## Supported Scope of Attributes 321 322Attributes not listed in the table below are supported by default. 323 324**Table 1** Unsupported attributes in the CommonAttribute API 325 326| Attribute | Supported/Unsupported| Error Message | Remarks | 327| ------------------------ | -------- | ------------------------- | ----------------------------------------- | 328| accessibilityChecked | Not supported | is not callable | - | 329| accessibilitySelected | Not supported | is not callable | - | 330| accessibilityTextHint | Not supported | is not callable | - | 331| accessibilityVirtualNode | Not supported | is not callable | Attributes that accept a CustomBuilder are not supported. | 332| animation | Not supported | Method not implemented. | Animation-related attributes are not supported. | 333| attributeModifier | Not supported | - | **attributeModifier** does not take effect when nested.| 334| background | Not supported | Method not implemented. | Attributes that accept a CustomBuilder are not supported. | 335| backgroundFilter | Not supported | is not callable | - | 336| bindContentCover | Not supported | Method not implemented. | Attributes that accept a CustomBuilder are not supported. | 337| bindContextMenu | Not supported | Method not implemented. | Attributes that accept a CustomBuilder are not supported. | 338| bindPopup | Not supported | Method not implemented. | Attributes that accept a CustomBuilder are not supported. | 339| bindSheet | Not supported | Method not implemented. | Attributes that accept a CustomBuilder are not supported. | 340| chainWeight | Not supported | is not callable | - | 341| compositingFilter | Not supported | is not callable | - | 342| drawModifier | Not supported | is not callable | Modifier-related attributes are not supported. | 343| foregroundFilter | Not supported | is not callable | - | 344| freeze | Not supported | is not callable | - | 345| gesture | Not supported | Method not implemented. | Gesture-related attributes are not supported. | 346| gestureModifier | Not supported | is not callable | Modifier-related attributes are not supported. | 347| onAccessibilityHover | Not supported | is not callable | - | 348| onChildTouchTest | Not supported | is not callable | - | 349| onDragStart | Not supported | Method not implemented. | Attributes that return a CustomBuilder are not supported. | 350| onPreDrag | Not supported | Method not implemented. | - | 351| onTouchIntercept | Not supported | is not callable | - | 352| onVisibleAreaChange | Not supported | Method not implemented. | - | 353| parallelGesture | Not supported | Method not implemented. | Gesture-related attributes are not supported. | 354| priorityGesture | Not supported | Method not implemented. | Gesture-related attributes are not supported. | 355| reuseId | Not supported | Method not implemented. | - | 356| stateStyles | Not supported | Method not implemented. | **stateStyles**-related attributes are not supported. | 357| useSizeType | Not supported | Method not implemented. | Deprecated attributes are not supported. | 358| visualEffect | Not supported | is not callable | - | 359| bindMenu | Partially supported| - | Attributes that accept a CustomBuilder are not supported. | 360| dragPreview | Partially supported| Builder is not supported. | Attributes that accept a CustomBuilder are not supported. | 361