No dashboards in this workspace yet.
}No dashboards in this workspace yet.
}| {title} | {value} |
Could not load revenue: {error?.message}
; } if (status !== "success" || !result) { returnLoading…
; } const slices = result.data().slices().toArray(); const values = slices.map((slice) => Number(slice.dataPoints()[0]?.rawValue ?? 0)); const max = Math.max(0, ...values); return (Loading regions…
; } const isChecked = (element: IAttributeElement) => { const inWorkingSelection = workingSelectionElements.some((el) => el.uri === element.uri); return isWorkingSelectionInverted ? !inWorkingSelection : inWorkingSelection; }; const toggle = (element: IAttributeElement) => { // Keep the selection mode and add or remove the value from the working list. const inWorkingSelection = workingSelectionElements.some((el) => el.uri === element.uri); const next = inWorkingSelection ? workingSelectionElements.filter((el) => el.uri !== element.uri) : [...workingSelectionElements, element]; onSelect(next, isWorkingSelectionInverted); }; return ( ); } ``` Two details matter here. The initial filter is a negative filter with an empty list, which GoodData.UI reads as "everything selected", and the controller reports it as an inverted selection: the working list holds the excluded values. The `toggle` function keeps that mode and only adds or removes the clicked value from the list, so values on pages you haven't loaded yet stay selected. Calling the controller's `onApply` commits the working selection and calls your `onApply` with an [`IAttributeFilter`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.iattributefilter/index.md) that executions understand. The controller loads elements in pages; for attributes with many values, call `onLoadNextElementsPage` when the user scrolls, as described in [useAttributeFilterController](https://www.gooddata.ai/docs/gooddata-ui/latest/filters/use-attribute-filter-controller/index.md). ## [Wire the filters into the execution](https://www.gooddata.ai/docs/gooddata-ui/latest/integrations/embedding/build-custom-frontend/#wire-the-filters-into-the-execution) Now hold the filters in state and pass them down. A period dropdown adds a date filter built in code. `newRelativeDateFilter` takes the date dataset, a granularity, and a range of periods where `0` is the current one, so `-11` to `0` is the last 12 months and `-1` to `-1` is last year. `newAllTimeFilter` removes the date restriction. Replace `App.tsx`: ```tsx import { type IAttributeFilter, type IDateFilter, newAllTimeFilter, newRelativeDateFilter } from "@gooddata/sdk-model"; import { BackendProvider, WorkspaceProvider } from "@gooddata/sdk-ui"; import { useMemo, useState } from "react"; import { backend } from "./backend.js"; import { DateDatasets } from "./catalog.js"; import { RegionFilter } from "./RegionFilter.js"; import { RevenueByCategory } from "./RevenueByCategory.js"; // WORKSPACE_ID is the global that the Quick start project injects with Vite's `define`. // In another app, use your workspace ID string. const workspaceId = WORKSPACE_ID; const periods = { all: newAllTimeFilter(DateDatasets.Date.ref), last12Months: newRelativeDateFilter(DateDatasets.Date.ref, "GDC.time.month", -11, 0), lastYear: newRelativeDateFilter(DateDatasets.Date.ref, "GDC.time.year", -1, -1), } satisfies Record{error?.message}
: null} > ); } ``` Render `