Skip to main content

Common Attribute API

Every controller returned by useAttribute(...) extends the base AttributeController, so the members below are available on all attribute controllers.

Getting the controller​

import { useAttribute } from "@expivi/product-configurator";

const attribute = useAttribute(configurator, attributeCid);

End-to-end example​

Read the current state, react to changes, then clean up:

import { useAttribute } from "@expivi/product-configurator";

const attribute = useAttribute(configurator, attributeCid);

console.log(attribute.data.identifier, attribute.isVisible);

const unsubscribe = attribute.subscribe(next => {
console.log("changed", next.configuredValue);
});

// later
unsubscribe();

Intercepting value changes​

The package exports a small typed API for running an async check before a value change is applied. It lets you confirm or veto a change (for example, asking the shopper to confirm a costly upgrade before it is committed).

import type {
BeforeSetValueContext,
BeforeSetValueResult,
BeforeSetValueHandler,
} from "@expivi/product-configurator";

The types are:

type BeforeSetValueContext = {
attributeCid: string;
valueCid: string;
};

type BeforeSetValueResult = {
confirmed: boolean;
};

type BeforeSetValueHandler = (context: BeforeSetValueContext) => Promise<BeforeSetValueResult>;

A handler receives the attribute/value cid pair being set and resolves to { confirmed: true } to allow the change or { confirmed: false } to veto it.

const attribute = useAttribute(configurator, attributeCid);

attribute.registerBeforeSetValue(async ({ attributeCid, valueCid }) => {
const confirmed = await showConfirmDialog(
`Apply ${valueCid} to ${attributeCid}?`,
);

return { confirmed };
});

// Remove the intercept when you no longer need it
attribute.unregisterBeforeSetValue();

Handlers are stored per attribute cid on the configurator, so registering again replaces the previous handler for that attribute.

API​

messagesController​

Reference to the shared MessagesController for this configurator.

registerBeforeSetValue(handler)​

Registers a BeforeSetValueHandler that runs before a value is set on this attribute. See Intercepting value changes.

unregisterBeforeSetValue()​

Removes the before-set-value handler for this attribute.

registerBeforeIncrementValue(handler)​

Registers a BeforeSetValueHandler used by quantity-oriented flows such as bundle quantity increments.

unregisterBeforeIncrementValue()​

Removes the before-increment handler for this attribute.

locale​

Returns the configurator's current locale (configurator.getLocale()).

data​

Returns the current typed attribute object. Throws if the attribute no longer exists.

isPristine​

Returns true when the attribute has not been modified by user interaction.

isDirty​

Returns the inverse of isPristine.

markAsDirty()​

Marks the attribute as user-modified. Call this from the UI layer on user interaction.

markAsPristine()​

Clears the dirty flag, typically after saving or resetting a configuration.

values​

Returns value entities from the current value page, preserving page order and active filtering.

allValues​

Returns every value entity for this attribute, regardless of the active page.

messages​

Returns messages scoped to this attribute's identifier.

isVisible​

Returns true when the attribute is not disallowed by rules.

isDisallowed​

Returns the raw disallowed state.

setDisallowed(disallowed)​

Updates the disallowed state and runs the controller-specific disallow hook when the attribute becomes disallowed.

isStatic​

Returns true for static-input attributes (no user selection).

isSingle​

Returns true for single-select attributes.

isMultiple​

Returns true for multi-select attributes.

isValuable​

Returns true when the attribute stores value entities such as artwork, boolean, list, modifier, or product values.

exists​

Returns true if the attribute still exists in the store.

clearDisallowedConfiguredValues()​

Clears configured values that are no longer part of the visible value set (as filtered by rules) and runs the controller-specific disallowed-value handling. Returns true if any values were changed.

produceSetValue(value)​

Low-level method that builds the next attribute state without committing it. In normal application code, call setValue(...) instead.

subscribe(callback)​

Subscribes to changes for this specific attribute. Returns an unsubscribe function.

const unsubscribe = attribute.subscribe(next => console.log(next));
unsubscribe();

subscribeMessages(callback)​

Subscribes to messages for this specific attribute. Returns an unsubscribe function.

setValue(value)​

Builds the next state with produceSetValue(...) and writes it to the store only if the configured value actually changed.

getValueByIdentifier(identifier)​

Finds a current-page value entity by identifier, or returns null.

getValueById(id)​

Finds a value entity by persistent id, or returns null.

getValueByCid(cid)​

Finds a value entity by runtime cid, or returns null.

getSelectableValueById(id)​

Returns the value with the given id only if it is on the current page or already part of the configured value (an off-page selection); otherwise returns null.

reset()​

Resets the attribute to its initial store state.

serialize()​

Serializes the attribute into the Expivi configuration format.

parse(data)​

Parses serialized attribute data into the current attribute.

loadValuePage(pageConfig)​

Loads a value page for this attribute, merging the given config over the current value-page config. Returns the loaded value cids.

selectedCategoryIds​

Returns the currently selected category ids from the value-page config.

selectedCategoryId​

Convenience getter for the first selected category id, or null. Use selectedCategoryIds for the full list.

setCategoryFilter(input)​

Sets the category filter and reloads the value page (combined with search and pagination). Accepts a single id (toggled on/off), an array of ids (replaces the selection), or null (clears it).

loadAvailableCategories()​

Fetches the list of available Category items for this attribute.

Each subscribe(...) / subscribeMessages(...) call returns an unsubscribe function. Always call it when the controller is torn down to release the store subscription.