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