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 12 13attributeModifier(modifier: AttributeModifier\<T>) 14 15Creates an attribute modifier. 16 17**Atomic service API**: This API can be used in atomic services since API version 12. 18 19**System capability**: SystemCapability.ArkUI.ArkUI.Full 20 21**Parameters** 22 23| Name | Type | Mandatory| Description | 24| -------- | --------------------- | ---- | ------------------------------------------------------------ | 25| 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.| 26 27## AttributeModifier\<T> 28 29You need a custom class to implement the **AttributeModifier** API. 30 31**Atomic service API**: This API can be used in atomic services since API version 12. 32 33### applyNormalAttribute 34applyNormalAttribute(instance: T) : void 35 36Applies the style of a component in the normal state. 37 38**Atomic service API**: This API can be used in atomic services since API version 12. 39 40### applyPressedAttribute 41applyPressedAttribute(instance: T) : void 42 43Applies the style of a component in the pressed state. 44 45**Atomic service API**: This API can be used in atomic services since API version 12. 46 47### applyFocusedAttribute 48applyFocusedAttribute(instance: T) : void 49 50Applies the style of a component in the focused state. 51 52**Atomic service API**: This API can be used in atomic services since API version 12. 53 54### applyDisabledAttribute 55applyDisabledAttribute(instance: T) : void 56 57Applies the style of a component in the disabled state. 58 59**Atomic service API**: This API can be used in atomic services since API version 12. 60 61### applySelectedAttribute 62applySelectedAttribute(instance: T) : void 63 64Applies the style of a component in the selected state. 65 66In the preceding APIs, **instance** indicates the component type. You can customize these APIs and use them with the **if/else **syntax. 67 68**Atomic service API**: This API can be used in atomic services since API version 12. 69 70**Parameters** 71 72| Name | Description | 73| -------------------- | ------------------------------------------------------------ | 74| 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.| 75 76**Value range of the instance parameter** 77 78AlphabetIndexerAttribute, 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--> 79 80**Supported attributes** 81 82Attributes whose input parameters are [CustomBuilder](ts-types.md#custombuilder8) or lamda expressions are not supported. In addition, gestures are not supported. Only the following events are supported: **onClick**, **onTouch**, **onAppear**, **onDisAppear**, **onMouse**, **onHover**, **onKeyEvent**, **onBlur**, **onFocus**, **onAreaChange**, **onSizeChange**, and **onGestureJudgeBegin**. Deprecated attributes are not supported. When an attribute not supported is used, the exception "Method not implemented " is thrown. 83## Custom Modifier 84Custom 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. 85 86**Supported custom modifiers** 87 88CommonModifier, 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 89**CommonModifier** can be used for unexposed components. 90 91**Precautions** 921. When a custom modifier is applied to a component, the corresponding attribute of the component takes effect. 932. 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. 943. With a custom modifier applied to two components, updating the attribute value of the custom modifier changes the corresponding attributes of both components. 954. 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. 965. The custom modifier does not support change observation for @State decorated variables. For details, see Example 2. 976. 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. 98 99## Example 100### Example 1 101```ts 102// xxx.ets 103class MyButtonModifier implements AttributeModifier<ButtonAttribute> { 104 isDark: boolean = false 105 applyNormalAttribute(instance: ButtonAttribute): void { 106 if (this.isDark) { 107 instance.backgroundColor(Color.Black) 108 } else { 109 instance.backgroundColor(Color.Red) 110 } 111 } 112} 113 114@Entry 115@Component 116struct attributeDemo { 117 @State modifier: MyButtonModifier = new MyButtonModifier() 118 119 build() { 120 Row() { 121 Column() { 122 Button("Button") 123 .attributeModifier(this.modifier) 124 .onClick(() => { 125 this.modifier.isDark = !this.modifier.isDark 126 }) 127 } 128 .width('100%') 129 } 130 .height('100%') 131 } 132} 133``` 134 135 136 137 138```ts 139// xxx.ets 140class MyButtonModifier implements AttributeModifier<ButtonAttribute> { 141 applyNormalAttribute(instance: ButtonAttribute): void { 142 instance.backgroundColor(Color.Black) 143 } 144 145 applyPressedAttribute(instance: ButtonAttribute): void { 146 instance.backgroundColor(Color.Red) 147 } 148} 149 150@Entry 151@Component 152struct attributePressedDemo { 153 @State modifier: MyButtonModifier = new MyButtonModifier() 154 155 build() { 156 Row() { 157 Column() { 158 Button("Button") 159 .attributeModifier(this.modifier) 160 } 161 .width('100%') 162 } 163 .height('100%') 164 } 165} 166``` 167 168 169### Example 2 170The custom modifier does not support change observation for @State decorated variables. 171```ts 172import { CommonModifier } from "@kit.ArkUI" 173 174class MyModifier extends CommonModifier { 175 applyNormalAttribute(instance: CommonAttribute) : void{ 176 super.applyNormalAttribute?.(instance); 177 } 178} 179 180@Component 181struct MyImage1 { 182 @Link modifier : CommonModifier 183 184 build(){ 185 Image($r("app.media.testImage")).attributeModifier(this.modifier as MyModifier) 186 } 187} 188@Entry 189@Component 190struct Index { 191 index : number = 0; 192 @State width1 : number = 100; 193 @State height1 : number = 100; 194 @State myModifier: CommonModifier = new MyModifier().width(this.width1).height(this.height1).margin(10) 195 196 build() { 197 Column() { 198 Button($r("app.string.EntryAbility_label")) 199 .margin(10) 200 .onClick(() => { 201 console.log("Modifier","onClick") 202 this.index ++; 203 if(this.index %2 === 1){ 204 this.width1 = 10; 205 console.log("Modifier","setGroup1") 206 }else{ 207 this.width1 = 10; 208 console.log("Modifier","setGroup2") 209 } 210 }) 211 MyImage1({modifier:this.myModifier}) 212 } 213 .width('100%') 214 } 215} 216``` 217 218### Example 3 219In 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. 220```ts 221import { CommonModifier } from "@kit.ArkUI" 222 223class MyModifier extends CommonModifier { 224 applyNormalAttribute(instance: CommonAttribute) : void{ 225 super.applyNormalAttribute?.(instance); 226 } 227 228 public setGroup1() : void { 229 this.borderStyle(BorderStyle.Dotted) 230 this.borderWidth(8) 231 } 232 233 public setGroup2() : void { 234 this.borderStyle(BorderStyle.Dashed) 235 this.borderWidth(8) 236 } 237} 238 239@Component 240struct MyImage1 { 241 @Link modifier : CommonModifier 242 243 build(){ 244 Image($r("app.media.testImage")).attributeModifier(this.modifier as MyModifier) 245 } 246} 247 248@Entry 249@Component 250struct Index { 251 @State myModifier: CommonModifier = new MyModifier().width(100).height(100).margin(10) 252 index : number = 0; 253 254 build() { 255 Column() { 256 Button($r("app.string.EntryAbility_label")) 257 .margin(10) 258 .onClick(() => { 259 console.log("Modifier","onClick") 260 this.index ++; 261 if(this.index %2 === 1){ 262 (this.myModifier as MyModifier).setGroup1() 263 console.log("Modifier","setGroup1") 264 }else{ 265 (this.myModifier as MyModifier).setGroup2() 266 console.log("Modifier","setGroup2") 267 } 268 }) 269 MyImage1({modifier:this.myModifier}) 270 } 271 .width('100%') 272 } 273} 274``` 275 276