• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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![attributeModifier_ifelse](figures/attributeModifier_ifelse.gif)
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![attributeModifier_ifelse](figures/attributeModifier_ifelse.gif)
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![attributeModifier2](figures/attributeModifier2.gif)
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![attributeModifier](figures/attributeModifier.gif)
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