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![attributeModifier_ifelse](figures/attributeModifier_ifelse.gif)
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![attributeModifier_ifelse](figures/attributeModifier_ifelse.gif)
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![attributeModifier2](figures/attributeModifier2.gif)  
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![attributeModifier](figures/attributeModifier.gif)
276