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