Attribute Modifier
With the attribute modifier, you can dynamically set component attributes, complete with the if/else syntax and polymorphic style.
NOTE
This feature is supported since API version 11. Updates will be marked with a superscript to indicate their earliest API version.
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.
For simple scenarios requiring conditional assignment of a single component attribute, ternary operators provide a concise alternative. Example: .width(isFullScreen ? 200 : 100).
attributeModifier supports custom components since API version 20.
attributeModifier
attributeModifier(modifier: AttributeModifier<T>): T
Creates an attribute modifier.
Atomic service API: This API can be used in atomic services since API version 12.
System capability: SystemCapability.ArkUI.ArkUI.Full
Parameters
| Name | Type | Mandatory | Description |
|---|---|---|---|
| modifier | AttributeModifier<T> | Yes | Modifier for dynamically setting attributes on the current component. The if/else syntax is supported. modifier: attribute modifier. You need to customize classes to implement the AttributeModifier API. |
Return value
| Type | Description |
|---|---|
| T | Current component. |
AttributeModifier<T>
You need a custom class to implement the AttributeModifier API.
Atomic service API: This API can be used in atomic services since API version 12.
System capability: SystemCapability.ArkUI.ArkUI.Full
NOTE
In the following APIs, setting the same value or object for the same attribute of the instance object will not trigger an update.
applyNormalAttribute
applyNormalAttribute?(instance: T): void
Applies the style of a component in the normal state.
Atomic service API: This API can be used in atomic services since API version 12.
System capability: SystemCapability.ArkUI.ArkUI.Full
Parameters
| Name | Type | Mandatory | Description |
|---|---|---|---|
| instance | T | Yes | 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. |
applyPressedAttribute
applyPressedAttribute?(instance: T): void
Applies the style of a component in the pressed state. For implementation examples, see Example 2: Implementing the Pressed State Effect with a Modifier and Example 8: Implementing the Pressed State Effect for a Custom Component with a Modifier.
Atomic service API: This API can be used in atomic services since API version 12.
System capability: SystemCapability.ArkUI.ArkUI.Full
Parameters
| Name | Type | Mandatory | Description |
|---|---|---|---|
| instance | T | Yes | 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. |
applyFocusedAttribute
applyFocusedAttribute?(instance: T): void
Applies the style of a component in the focused state. For the implementation example, see Example 5: Setting the Focused State Style with a Modifier.
Atomic service API: This API can be used in atomic services since API version 12.
System capability: SystemCapability.ArkUI.ArkUI.Full
Parameters
| Name | Type | Mandatory | Description |
|---|---|---|---|
| instance | T | Yes | 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. |
applyDisabledAttribute
applyDisabledAttribute?(instance: T): void
Applies the style of a component in the disabled state. For the implementation example, see Example 6: Setting the Disabled State Style with a Modifier.
Atomic service API: This API can be used in atomic services since API version 12.
System capability: SystemCapability.ArkUI.ArkUI.Full
Parameters
| Name | Type | Mandatory | Description |
|---|---|---|---|
| instance | T | Yes | 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. |
applySelectedAttribute
applySelectedAttribute?(instance: T): void
Applies the style of a component in the selected state.
In the preceding APIs, instance indicates the component type. You can customize these APIs and use them with the **if/else **syntax. For the implementation example, see Example 7: Setting the Selected State Style with a Modifier.
Atomic service API: This API can be used in atomic services since API version 12.
System capability: SystemCapability.ArkUI.ArkUI.Full
Parameters
| Name | Type | Mandatory | Description |
|---|---|---|---|
| instance | T | Yes | 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. |
Value range of the instance parameter
AlphabetIndexerAttribute, 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, IndicatorComponentAttribute, 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, UIPickerComponentAttribute, EffectComponentAttribute, FormComponentAttribute, PluginComponentAttribute, RemoteWindowAttribute, and UIExtensionComponentAttribute
Supported attributes
- Attributes that accept or return a CustomBuilder are not supported.
- Attributes that accept a modifier type, such as attributeModifier, drawModifier, and gestureModifier, are not supported.
- Attribute related to animation are not supported.
- Attributes of the gesture type are not supported.
- Attribute related to stateStyles are not supported.
- Deprecated attributes are not supported.
- Built-in component attributes are not supported.
When unsupported or unimplemented attributes are used, exceptions such as "Method not implemented.", "is not callable", or "Builder is not supported." are thrown. For details about the supported modifiers, see attributeModifier Support for Attributes and Events.
Custom Modifier
Custom 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.
Supported custom modifiers
CommonModifier, 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, and UIPickerComponentModifier
CommonModifier can be used for unexposed components.
Precautions
- When a custom modifier is applied to a component, the corresponding attribute of the component takes effect.
- 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.
- With a custom modifier applied to two components, updating the attribute value of the custom modifier changes the corresponding attributes of both components.
- 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.
- Custom modifiers do not support change detection of state data decorated with @State. For details, see Example 3: Understanding Custom Modifiers Do Not Support State Data Changes).
- 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.
Example
Example 1: Switching the Background Color with a Modifier
This example demonstrates how to switch the background color of a Button component by binding it to a modifier.
// xxx.ets
// Set the custom AttributeModifier for the Button component attributes.
class MyButtonModifier implements AttributeModifier<ButtonAttribute> {
public isDark: boolean = false;
applyNormalAttribute(instance: ButtonAttribute): void {
if (this.isDark) {
instance.backgroundColor(Color.Black);
} else {
instance.backgroundColor(Color.Red);
}
}
}
@Entry
@Component
struct attributeDemo {
@State modifier: MyButtonModifier = new MyButtonModifier();
build() {
Row() {
Column() {
Button("Button")
.attributeModifier(this.modifier)
.onClick(() => {
this.modifier.isDark = !this.modifier.isDark;
})
}
.width('100%')
}
.height('100%')
}
}

Example 2: Implementing the Pressed State Effect with a Modifier
This 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.
// xxx.ets
// Set the custom AttributeModifier for the Button component attributes.
class MyButtonModifier implements AttributeModifier<ButtonAttribute> {
applyNormalAttribute(instance: ButtonAttribute): void {
instance.backgroundColor(Color.Black);
}
applyPressedAttribute(instance: ButtonAttribute): void {
instance.backgroundColor(Color.Red);
}
}
@Entry
@Component
struct attributePressedDemo {
@State modifier: MyButtonModifier = new MyButtonModifier();
build() {
Row() {
Column() {
Button("Button")
.attributeModifier(this.modifier)
}
.width('100%')
}
.height('100%')
}
}

Example 3: Understanding Custom Modifiers Do Not Support State Data Changes
This 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.
import { CommonModifier } from "@kit.ArkUI";
const TEST_TAG: string = "AttributeModifier";
// Set the custom AttributeModifier for the universal component attributes.
class MyModifier extends CommonModifier {
applyNormalAttribute(instance: CommonAttribute): void {
super.applyNormalAttribute?.(instance);
}
}
@Component
struct MyImage1 {
@Link modifier: CommonModifier;
build() {
Image($r("app.media.startIcon")).attributeModifier(this.modifier as MyModifier)
}
}
@Entry
@Component
struct Index {
index: number = 0;
@State width1: number = 100;
@State height1: number = 100;
@State myModifier: CommonModifier = new MyModifier().width(this.width1).height(this.height1).margin(10);
build() {
Column() {
Button($r("app.string.EntryAbility_label"))
.margin(10)
.onClick(() => {
console.info(TEST_TAG, "onClick");
this.index++;
if (this.index % 2 === 1) {
this.width1 = 10;
console.info(TEST_TAG, "setGroup1");
} else {
this.height1 = 10;
console.info(TEST_TAG, "setGroup2");
}
})
MyImage1({ modifier: this.myModifier })
}
.width('100%')
}
}

Example 4: Combining Modifier and Custom Modifier Attributes
This example demonstrates how to set width and height through a custom modifier. When the button is clicked, borderStyle and borderWidth are configured, with all four attributes taking effect simultaneously.
import { CommonModifier } from "@kit.ArkUI";
const TEST_TAG: string = "AttributeModifier";
// Set the custom AttributeModifier for the universal component attributes.
class MyModifier extends CommonModifier {
applyNormalAttribute(instance: CommonAttribute): void {
super.applyNormalAttribute?.(instance);
}
public setGroup1(): void {
this.borderStyle(BorderStyle.Dotted);
this.borderWidth(8);
}
public setGroup2(): void {
this.borderStyle(BorderStyle.Dashed);
this.borderWidth(8);
}
}
@Component
struct MyImage1 {
@Link modifier: CommonModifier;
build() {
Image($r("app.media.startIcon")).attributeModifier(this.modifier as MyModifier)
}
}
@Entry
@Component
struct Index {
@State myModifier: CommonModifier = new MyModifier().width(100).height(100).margin(10);
index: number = 0;
build() {
Column() {
Button($r("app.string.EntryAbility_label"))
.margin(10)
.onClick(() => {
console.info(TEST_TAG, "onClick");
this.index++;
if (this.index % 2 === 1) {
(this.myModifier as MyModifier).setGroup1();
console.info(TEST_TAG, "setGroup1");
} else {
(this.myModifier as MyModifier).setGroup2();
console.info(TEST_TAG, "setGroup2");
}
})
MyImage1({ modifier: this.myModifier })
}
.width('100%')
}
}

Example 5: Setting the Focused State Style with a Modifier
This example demonstrates how to implement a focused state style for a Button component by binding it to a modifier. After Button2 is clicked, the Button component displays the focused style when it has focus.
// Set the custom AttributeModifier for the Button component attributes.
class MyButtonModifier implements AttributeModifier<ButtonAttribute> {
applyNormalAttribute(instance: ButtonAttribute): void {
instance.backgroundColor(Color.Blue);
}
applyFocusedAttribute(instance: ButtonAttribute): void {
instance.backgroundColor(Color.Green);
}
}
@Entry
@Component
struct attributeDemo {
@State modifier: MyButtonModifier = new MyButtonModifier();
@State isDisable: boolean = true;
build() {
Row() {
Column() {
Button("Button")
.attributeModifier(this.modifier)
.enabled(this.isDisable)
.id("app")
Divider().vertical(false).strokeWidth(15).color(Color.Transparent)
Button("Button2")
.onClick(() => {
this.getUIContext().getFocusController().activate(true);
this.getUIContext().getFocusController().requestFocus("app");
})
}
.width('100%')
}
.height('100%')
}
}

Example 6: Setting the Disabled State Style with a Modifier
This example demonstrates how to implement a disabled state style for a Button component by binding it to a modifier. After Button2 is clicked, the Button component displays the disabled style when it is disabled.
// Set the custom AttributeModifier for the Button component attributes.
class MyButtonModifier implements AttributeModifier<ButtonAttribute> {
applyDisabledAttribute(instance: ButtonAttribute): void {
instance.width(200);
}
}
@Entry
@Component
struct attributeDemo {
@State modifier: MyButtonModifier = new MyButtonModifier();
@State isDisable: boolean = true;
build() {
Row() {
Column() {
Button("Button")
.attributeModifier(this.modifier)
.enabled(this.isDisable)
Divider().vertical(false).strokeWidth(15).color(Color.Transparent)
Button("Button2")
.onClick(() => {
this.isDisable = !this.isDisable;
})
}
.width('100%')
}
.height('100%')
}
}

Example 7: Setting the Selected State Style with a Modifier
This example demonstrates how to implement a selected state style for a Radio component by binding it to a modifier.
// Set the custom AttributeModifier for the Radio component attributes.
class MyRadioModifier implements AttributeModifier<RadioAttribute> {
applyNormalAttribute(instance: RadioAttribute): void {
instance.backgroundColor(Color.Blue);
}
applySelectedAttribute(instance: RadioAttribute): void {
instance.backgroundColor(Color.Red);
instance.borderWidth(2);
}
}
@Entry
@Component
struct attributeDemo {
@State modifier: MyRadioModifier = new MyRadioModifier();
@State value: boolean = false;
@State value2: boolean = false;
build() {
Row() {
Column() {
Radio({ value: 'Radio1', group: 'radioGroup1' })
.checked(this.value)
.height(50)
.width(50)
.borderWidth(0)
.borderRadius(30)
.onClick(() => {
this.value = !this.value;
})
.attributeModifier(this.modifier)
}
.width('100%')
}
.height('100%')
}
}

Example 8: Implementing the Pressed State Effect for a Custom Component with a Modifier
This example demonstrates how to implement a pressed state effect for a custom component (Common) by binding it to a modifier.
// xxx.ets
// Set the custom AttributeModifier for the custom component attributes.
class CustomModifier implements AttributeModifier<CommonAttribute> {
applyNormalAttribute(instance: CommonAttribute): void {
instance.backgroundColor(Color.Blue)
}
applyPressedAttribute(instance: CommonAttribute): void {
instance.backgroundColor(Color.Gray)
}
}
@Entry
@Component
struct attributePressedDemo {
@State modifier: CustomModifier = new CustomModifier()
build() {
Row() {
Column() {
ChildComponent()
.attributeModifier(this.modifier)
}
.width('100%')
}
.height('100%')
}
}
// Custom component
@Component
struct ChildComponent {
build() {
Text("common")
.fontColor(Color.White)
.fontSize(28)
.textAlign(TextAlign.Center)
.width('35%')
.height('10%')
}
}
