> Documentation index: https://www.gooddata.ai/docs/gooddata-ui/llms.txt lists every page of these docs as Markdown.

# Working with attributes

> Create and modify IAttribute objects with newAttribute, apply optional local identifiers and alias overrides.

API reference: [newAttribute()](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.newattribute/index.md) (function), [IAttribute](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.iattribute/index.md) (interface), [newAttributeSort()](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.newattributesort/index.md) (function), [IAttributeElement](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.iattributeelement/index.md) (interface), [IElementsQuery](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-backend-spi/sdk-backend-spi.ielementsquery/index.md) (interface)

Create [`IAttribute`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.iattribute/index.md) objects with `newAttribute`, and adjust existing ones with `modifyAttribute`. An attribute in an execution always references a display form (label), not the attribute itself, because the display form decides which values appear in the result.

`newAttribute` takes a display form identifier (treated as `idRef(id, "displayForm")`) or an [`ObjRef`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.objref/index.md), and an optional callback that receives an [`AttributeBuilder`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.attributebuilder/index.md):

| Builder method | Effect |
|----------------|--------|
| `alias(text)` | Overrides the display label. |
| `localId(id)` | Sets the local identifier that other parts of the execution use to reference the attribute. Without it, the builder derives a stable one from the alias and the display form. |
| `showAllValues(true)` | Returns all values, also those without data. |
| `displayForm(ref)` | Switches to another display form. |

## [Basic usage](https://www.gooddata.ai/docs/gooddata-ui/latest/data-layer/data-model/attributes/#basic-usage)

```ts
import { newAttribute, idRef } from "@gooddata/sdk-model";

// Create an attribute from a display form identifier
const region = newAttribute("region.displayform.id");

// Customize with the builder (alias, localId, etc.)
const regionWithAlias = newAttribute(
    idRef("region.displayform.id", "displayForm"),
    (b) => b.alias("Sales Region").localId("region"),
);
```

## [Attribute fields](https://www.gooddata.ai/docs/gooddata-ui/latest/data-layer/data-model/attributes/#attribute-fields)

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `attribute` | [`IAttributeBody`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.iattributebody/index.md) | Yes | Body of the attribute, wrapping the display form ref, optional alias, and `localIdentifier`. |

## [Notes](https://www.gooddata.ai/docs/gooddata-ui/latest/data-layer/data-model/attributes/#notes)

Use `modifyAttribute` instead of `newAttribute` when you already have an [`IAttribute`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.iattribute/index.md) and want to tweak it — it preserves the original `localIdentifier` by default, which is important because executions cross-reference measures and attributes by that id. All local identifiers inside a single execution definition must be unique; supply an explicit `localId` when your execution references the same attribute twice with different aliases or sorts. Refer to display forms by identifier: GoodData Cloud and GoodData.CN do not support URI references.

## [Load attribute values](https://www.gooddata.ai/docs/gooddata-ui/latest/data-layer/data-model/attributes/#load-attribute-values)

The [`AttributeFilter`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-ui-filters/sdk-ui-filters.attributefilter/index.md) component loads the values it offers for you. To load them yourself, for example for a custom
picker, a saved-selection check, or a server-side search, use the attributes service.

```ts
import { type IAnalyticalBackend, type IElementsQueryResult } from "@gooddata/sdk-backend-spi";
import { attributeDisplayFormRef } from "@gooddata/sdk-model";
import * as Md from "./catalog.js";

const productDisplayForm = attributeDisplayFormRef(Md.Product.Name);

export function searchProducts(
    backend: IAnalyticalBackend,
    workspace: string,
    text: string,
): Promise<IElementsQueryResult> {
    return backend
        .workspace(workspace)
        .attributes()
        .elements()
        .forDisplayForm(productDisplayForm)
        .withLimit(50)
        .withOffset(0)
        .withOptions({ filter: text })
        .query();
}
```

The result is an [`IPagedResource`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-backend-spi/sdk-backend-spi.ipagedresource/index.md) of [`IAttributeElement`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.iattributeelement/index.md). Read the first page from `items`, the total from
`totalCount`, and call `next()` or `all()` for more. Each element has a `title` and a `uri`, which on GoodData Cloud
and GoodData.CN holds the value of the primary label. Both are `null` for the empty value.

| Method | Effect |
|--------|--------|
| [`withLimit(n)`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-backend-spi/sdk-backend-spi.ielementsquery/index.md#ielementsquerywithlimit), [`withOffset(n)`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-backend-spi/sdk-backend-spi.ielementsquery/index.md#ielementsquerywithoffset) | Page size and start. The analytics engine caps the page size. |
| [`withOptions({ filter })`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-backend-spi/sdk-backend-spi.ielementsquery/index.md#ielementsquerywithoptions) | Server-side substring match on the title. |
| [`withOptions({ order })`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-backend-spi/sdk-backend-spi.ielementsquery/index.md#ielementsquerywithoptions) | `"asc"` or `"desc"` by title. |
| [`withOptions({ elements })`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-backend-spi/sdk-backend-spi.ielementsquery/index.md#ielementsquerywithoptions) | Load specific values only: `{ values: [...] }` (values of this display form) or `{ primaryValues: [...] }` (values of the primary label). `{ uris: [...] }` is not supported. |
| [`withOptions({ complement: true })`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-backend-spi/sdk-backend-spi.ielementsquery/index.md#ielementsquerywithoptions) | Return every value except those in `elements`. |
| [`withAttributeFilters([{ attributeFilter, overAttribute }])`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-backend-spi/sdk-backend-spi.ielementsquery/index.md#ielementsquerywithattributefilters) | Restrict to values that exist with the given parent selection. This is how dependent filters work. |
| [`withDateFilters(filters)`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-backend-spi/sdk-backend-spi.ielementsquery/index.md#ielementsquerywithdatefilters) | Restrict to values that have data in the date range. |
| [`withMeasures(measures)`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-backend-spi/sdk-backend-spi.ielementsquery/index.md#ielementsquerywithmeasures) | Not supported on GoodData Cloud and GoodData.CN; it throws [`NotSupported`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-backend-spi/sdk-backend-spi.notsupported/index.md). Use `withAvailableElementsOnly` instead. |
| [`withAvailableElementsOnly(refs)`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-backend-spi/sdk-backend-spi.ielementsquery/index.md#ielementsquerywithavailableelementsonly) | Restrict to values valid for the objects in `refs`. |
| `withSignal(signal)` | Cancel through an `AbortSignal`. |

Load only what you show. Every call is a round trip, and the caching decorator sends a request that carries a
`filter` to the analytics engine unless it already holds the complete element list for that display form; see [Improve dashboard performance](https://www.gooddata.ai/docs/gooddata-ui/latest/dashboard-plugins/dashboard-performance/index.md).

In React, drive the query with [usePagedResource](https://www.gooddata.ai/docs/gooddata-ui/latest/data-layer/use-paged-resource/index.md) to accumulate pages, or with
[useCancelablePromise](https://www.gooddata.ai/docs/gooddata-ui/latest/data-layer/use-cancelable-promise/index.md) for a single page. To build a filter from the loaded
elements, pass their titles as `{ values: [element.title] }` to `newPositiveAttributeFilter`; see
[Inspect filter objects](https://www.gooddata.ai/docs/gooddata-ui/latest/filters/inspecting-filters/index.md).

### [Check a saved selection](https://www.gooddata.ai/docs/gooddata-ui/latest/data-layer/data-model/attributes/#check-a-saved-selection)

Values stored in a URL or in user preferences can disappear from the data. Ask for exactly those values and compare
what came back:

```ts
import { type IAnalyticalBackend } from "@gooddata/sdk-backend-spi";
import { attributeDisplayFormRef } from "@gooddata/sdk-model";
import * as Md from "./catalog.js";

export async function stillValid(backend: IAnalyticalBackend, workspace: string, saved: string[]): Promise<string[]> {
    const result = await backend
        .workspace(workspace)
        .attributes()
        .elements()
        .forDisplayForm(attributeDisplayFormRef(Md.Region.Default))
        .withOptions({ elements: { values: saved } })
        .query();

    const found = new Set(result.items.map((element) => element.title));

    return saved.filter((value) => found.has(value));
}
```

## [Props](https://www.gooddata.ai/docs/gooddata-ui/latest/data-layer/data-model/attributes/#props)

| Prop | Type | Required | Description | Inherited from |
|------|------|----------|-------------|----------------|
| [`attribute`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.iattribute/index.md#iattributeattribute) | [`IAttributeBody`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.iattributebody/index.md) | Yes | — | — |
