Inspect filter objects
Filters reach your code as IFilter[] from useWidgetFilters, insightFilters, the onApply callback of AttributeFilter, or a drill event. IFilter is a union, and each member wraps its data in a differently named body, such as positiveAttributeFilter or relativeDateFilter. Read them with the accessors below instead of opening those bodies.
Split filters by kind
Pass the type guards straight to filter, find, or some. TypeScript narrows the result for you.
import { isAttributeFilter, isDateFilter, type IFilter } from "@gooddata/sdk-model";
function splitFilters(filters: IFilter[]) {
return {
attributeFilters: filters.filter(isAttributeFilter),
dateFilters: filters.filter(isDateFilter),
};
}
For a finer split, use isAbsoluteDateFilter, isRelativeDateFilter, isAllTimeDateFilter, isMeasureValueFilter, and isRankingFilter.
Find the filter for a display form
filterObjRef returns the display form of an attribute filter and the dataset of a date filter. Compare it with areObjRefsEqual, never by reading identifier fields. See Working with object references.
import {
areObjRefsEqual,
attributeDisplayFormRef,
filterObjRef,
isAttributeFilter,
type IAttributeFilter,
type IFilter,
type ObjRef,
} from "@gooddata/sdk-model";
import * as Md from "./catalog.js";
function attributeFilterFor(filters: IFilter[], displayForm: ObjRef): IAttributeFilter | undefined {
return filters
.filter(isAttributeFilter)
.find((filter) => areObjRefsEqual(filterObjRef(filter), displayForm));
}
const productFilter = attributeFilterFor(filters, attributeDisplayFormRef(Md.Product.Name));
To find a date filter for a dataset, compare filterObjRef(dateFilter) with the dataset reference, for example Md.DateDatasets.Closed.ref.
Read the selected elements
filterAttributeElements works for positive and negative filters (IAttributeFilterWithSelection). The result is { values } for filters created from element values, which is the usual case on GoodData Cloud and GoodData.CN. Filters created with the legacy { uris } form return { uris }, so narrow the result before you read it.
import {
filterAttributeElements,
isAttributeElementsByRef,
type IAttributeFilterWithSelection,
} from "@gooddata/sdk-model";
function selectedElements(filter: IAttributeFilterWithSelection): Array<string | null> {
const selection = filterAttributeElements(filter);
return isAttributeElementsByRef(selection) ? selection.uris : selection.values;
}
A null element stands for the empty value. Filter it out only when your UI has no way to show it.
You don’t need to read .positiveAttributeFilter.in or .negativeAttributeFilter.notIn yourself; filterAttributeElements handles both. Check the polarity only to label the selection, for example “excludes” instead of “includes”, with isNegativeAttributeFilter(filter).
Detect an empty selection
filterIsEmpty returns true when an attribute filter selects no elements. A negative filter with an empty selection excludes nothing; that is how the SDK represents a filter set to “All”. A positive filter with an empty selection matches nothing.
import { filterIsEmpty, isAttributeFilter, type IFilter } from "@gooddata/sdk-model";
const activeAttributeFilters = filters.filter(isAttributeFilter).filter((filter) => !filterIsEmpty(filter));
Replace the selection
Filters are immutable. Build a new one with the same display form, polarity, and local identifier. Keeping the local identifier matters when other parts of the execution definition refer to the filter.
import {
filterLocalIdentifier,
filterObjRef,
isNegativeAttributeFilter,
newNegativeAttributeFilter,
newPositiveAttributeFilter,
type IAttributeElements,
type INegativeAttributeFilter,
type IPositiveAttributeFilter,
} from "@gooddata/sdk-model";
function withElements(
filter: IPositiveAttributeFilter | INegativeAttributeFilter,
elements: IAttributeElements,
): IPositiveAttributeFilter | INegativeAttributeFilter {
const displayForm = filterObjRef(filter);
return isNegativeAttributeFilter(filter)
? newNegativeAttributeFilter(displayForm, elements, filterLocalIdentifier(filter))
: newPositiveAttributeFilter(displayForm, elements, filterLocalIdentifier(filter));
}
Both factories accept the IAttributeElements object you got from filterAttributeElements, so you can copy a selection from one filter to another without unpacking it.
Notes
filterAttributeElements(filter)returnsundefinedwhen you pass a filter that has no element selection, such as a date filter or a text-based attribute filter. Narrow withisAttributeFilterWithSelectionfirst to get the non-optional overload;isAttributeFilteralone also matchesIArbitraryAttributeFilterandIMatchAttributeFilter.filterObjRef(filter)isundefinedfor measure value and ranking filters, which have no single object reference.- When you pass plain values instead of an
IAttributeElementsobject,newPositiveAttributeFilteraccepts(string | null)[]butnewNegativeAttributeFilteraccepts onlystring[]. Pass theIAttributeElementsobject to sidestep the difference. - Dashboard-level filters (
FilterContextItem) have a different shape fromIFilter. Read them with the selectors described in useDashboardSelector, and useuseWidgetFiltersto get the effectiveIFilter[]for a widget.
Related
Create attribute, date, measure-value, and ranking filters and apply them to charts, InsightView, or individual measures.
Compare, key, narrow, and print ObjRef values with areObjRefsEqual, serializeObjRef, and the type guards instead of reading identifier fields by hand.
Resolve the effective filters of a dashboard widget and visualization, ready to apply with insightSetFilters before execution.
Configure AttributeFilter with a filter definition or placeholder, handle selection changes, choose selection behavior, and replace its UI components.
Build fully custom attribute filter UIs with SDK-managed state, elements loading, and apply callbacks.