Hello team, Is there anyway for WebComponents to ...
# gooddata-cloud
j
Hello team, Is there anyway for WebComponents to have the filters saved even after refreshing the page? Currently everytime I refresh it resets do default. Are there any work arounds used in the community? cc: @Fardim kaiser
k
There is currently no built‑in way for GoodData Web Components to persist filter values across page reloads; they always revert to the dashboard’s default filter context when the page is refreshed. This was confirmed by GoodData support: the “auto‑save last state” (local‑storage–based persistence) is only available in the standard portal UI, not in component embedding, and there is “no other way to pass values into the web component from the web browser” at the moment.[[Web components filters](https://gooddataconnect.slack.com/archives/C04S1MSLEAW/p1754485967458109?thread_ts=1754485967.458109&cid=C04S1MSLEAW)] Because of that, there is also no documented workaround pattern from the community for Web Components similar to what’s possible with React
<Dashboard />
(where you can use dispatch commands and custom persistence in your app). The referenced thread explicitly concludes that persistence via the browser (cookies/localStorage) is not supported and suggests raising it as product feedback.[[Web components filters](https://gooddataconnect.slack.com/archives/C04S1MSLEAW/p1754485967458109?thread_ts=1754485967.458109&amp;cid=C04S1MSLEAW)] If you need per‑user persistent filters today, the only approaches documented in the knowledge sources use React SDK / embedded dashboards (dispatch commands, custom storage, or custom filter contexts), not Web Components.[[React embedded filters](https://gooddataconnect.slack.com/archives/C04S1MSLEAW/p1718999863146809?thread_ts=1718999863.146809&amp;cid=C04S1MSLEAW); [React dashboard filters](https://gooddataconnect.slack.com/archives/C01UR5BGAHY/p1728021264724689?thread_ts=1728021264.724689&amp;cid=C01UR5BGAHY)] So, based on the available information: - Web Components: no supported way to persist filters after refresh; no official workaround documented. - If this is critical, the recommended next step is to file product feedback (as was done in the referenced case) or consider switching to React embedding where custom persistence logic is possible.
m
@Joaquim Grilo - if gooddata can't do it, can your webapp save context in a cookie/session, then pre-populate parameters for webcomponents on page reload?
f
Copy code
gdElement.addEventListener('GDC.DASH/EVT.FILTER_CONTEXT.ATTRIBUTE_FILTER.SELECTION_CHANGED', this.onDashboardFilterChange.bind(this));

onDashboardFilterChange(e: Event) {
		const detail = (e as CustomEvent).detail;
		const filters = detail?.dashboard?.filterContext?.filters;
		if (Array.isArray(filters)) {
			this.dashboardFilters.push(...filters);
			localStorage.setItem('latestDashboardFilters', JSON.stringify(this.dashboardFilters));
		} else {
			this.dashboardFilters.push(detail.filter);
			localStorage.setItem('latestDashboardFilters', JSON.stringify(this.dashboardFilters));
		}
	}
We are trying to capture the filter changes here and store them locally to reuse on page refresh • But 'GDC.DASH/EVT.FILTER_CONTEXT.ATTRIBUTE_FILTER.SELECTION_CHANGED' cannot capture the Date Filter chnanges. • Please let us know the event name to capture the Date Filter changes
Copy code
gdElement.addEventListener('GDC.DASH/EVT.INITIALIZED', () => {
	this.pushFilters(gdElement);
});

	private pushFilters(dashboardEl: HTMLElement & { contentWindow?: Window }) {
		const msg = {
			gdc: {
				product: "dashboard",
				event: {
					name: "setFilterContext",
					data: { filters: this.dashboardFilters }
				}
			}
		};

		if (dashboardEl.contentWindow) {
		    dashboardEl.contentWindow.postMessage(msg, "*");
		} else {
		    window.postMessage(msg, "*");
		}

		// Optionally listen for confirmation
		window.addEventListener('message', (ev: MessageEvent) => {
			try {
				const g = (ev.data as any).gdc;
				if (g?.product === 'dashboard' && g.event?.name === 'setFilterContextFinished') {
				console.log('Filters applied');
				}
			} catch (e) {
				// ignore
			}
		});
	}
Then we are trying to push the stored filters on GD Dashboard Load through this eventlistener and pushFilters method. but its not working
Copy code
{
  "gdc": {
    "product": "dashboard",
    "event": {
      "name": "setFilterContext",
      "data": {
        "filters": [
          {
            "attributeFilter": {
              "title": "Days of week",
              "displayForm": {
                "identifier": "sorted_week_part",
                "type": "displayForm"
              },
              "localIdentifier": "sorted_week_part_4_attributeFilter",
              "attributeElements": {
                "uris": [
                  "1 - Monday",
                  "4 - Thursday",
                  "5 - Friday"
                ]
              },
              "negativeSelection": false,
              "selectionMode": "multi"
            }
          },
          {
            "attributeFilter": {
              "title": "Days of week",
              "displayForm": {
                "identifier": "sorted_week_part",
                "type": "displayForm"
              },
              "localIdentifier": "sorted_week_part_4_attributeFilter",
              "attributeElements": {
                "uris": [
                  "1 - Monday",
                  "4 - Thursday",
                  "5 - Friday"
                ]
              },
              "negativeSelection": false,
              "selectionMode": "multi"
            }
          },
          {
            "attributeFilter": {
              "title": "Days of week",
              "displayForm": {
                "identifier": "sorted_week_part",
                "type": "displayForm"
              },
              "localIdentifier": "sorted_week_part_4_attributeFilter",
              "attributeElements": {
                "uris": [
                  "4 - Thursday",
                  "5 - Friday"
                ]
              },
              "negativeSelection": false,
              "selectionMode": "multi"
            }
          }
        ]
      }
    }
  }
}
This is the msg object that we are passing in the window.postMessage(msg, "*"); Please check the object is correct and let us know if we have to do some changes here
j
Hi Fardim, I have delegated your question to our Technical Team. They will review and get back to you as soon as possible.
❤️ 1
m
Hi team, this is Moises with the Technical Support team. Thank you for sharing the details. I’ve reviewed the entire thread as well as your implementation, and I can reliably reproduce the current behavior. Unfortunately, I have not been able to make the filter values persist on the dashboard component either. I also noticed you previously had the same inquiry here: https://gooddataconnect.slack.com/archives/C04S1MSLEAW/p1754485967458109 Based on the current version of Web Components, nothing significant in terms of what's possible to set in the dashboard as a way of reading an event listener has changed. That said, I’ve reached out to our devs to see if there are any alternative approaches we may be able to suggest. All in all, this functionality is not officially supported at the moment, so any custom solution would fall under the scope of our Professional Services team. As a temporary workaround, you might consider using the built-in Saved View functionality, but I understand this may not fully satisfy your use case, so could you let us know how critical this missing functionality is for you? Looping in your Account Manager, @Thiago Alves, for visibility in case further discussion is needed.
👀 1
s
How is an end user expected to use this functionality if the filters don’t persist? What other dashboard product resets filters every time the page is loaded? @Moises Morales
Example, a user selects a custom date, and 4 or 5 other filters. Then flips to another view, then flips back and has to again select a custom date, and 4 or 5 other filters. Is this acceptable functionality? Maybe i’m not understanding what the intended user experience is that GoodData has built.
m
Hi Sameer, thank you for following up. I agree that the current behavior is not optimal, and there is already a product feedback entry in our records regarding this missing functionality. I will go ahead and submit another entry on your behalf to further highlight it to our developers. At the moment, I can only suggest working with the saved views feature or using iframes. My apologies if this is not the answer you were hoping for. If further discussion is needed, depending on how critical this feature is for you, please do not hesitate to reach out directly to my colleague, @Thiago Alves. Thank you for your understanding.
p
🎉 New note created.
🎉 New note created.
f
Hi @Thiago Alves please check once my message here In summary • I am trying to capture SELECTION_CHANGED event from Gooddata and storing them locally. • On refresh, after Gooddata triggered the INITIALIZED event, I am passing the stored filters through window.postMessage method. but Gooddata is not receiving my filters. • Please check the thread above, I have shared the payload of the window.postMessage. Let me know if there is any wrong in the payload.
s
@Moises Morales @Thiago Alves we were looking for feedback on this code that Fardim has shared, we are trying to build our own workaround for persisting the filter selections and need your help ASAP please.
t
Hello @Fardim Kaiser and @Sameer Hasan, At the moment, GoodData Web Components don’t support persisting dashboard filters across a full page refresh. On reload, the dashboard resets to its default filter context, and there isn’t a supported API or event flow that reliably captures and reapplies all filters, including date filters. Because of that, custom approaches using local storage or postMessage aren’t something we can guarantee to work. As temporary alternatives, we recommend using Saved Views or iframe embedding, depending on the use case. This limitation is already tracked as product feedback. That said, I’ll double-check with our Technical team regarding the code you shared to see if they have any additional guidance or insights to add. If filter persistence is a critical requirement, our Professional Services team can help evaluate custom approaches or alternative UX patterns, with the understanding that this would be outside standard product support and handled separately. Happy to follow up via email with more details regarding the PS team cooperation, if helpful.
s
If there are no APIs or events, what will the professional services team do?
t
Hello @Sameer Hasan, I have some updates: We did some fixes and updated the NPM packages. Could you please try updating to the latest versions and retest?
Copy code
Specifically: npm i -g @gooddata/code-cli
As a fallback option, dashboards can also be managed via dashboard views with predefined filters, though this requires handling which attributes or views should be applied per user after login. Link to that API: https://www.gooddata.com/docs/api-docs/api-reference/filter-views#post-filter-views
f
Hi @Thiago Alves I will check the endpoint soon and will update here.
👍 1
t
Hello @Fardim Kaiser, Any updates?
f
Hi @Thiago Alves this endpoints don't help us. And we are not using the @gooddata/code-cli. We are using script to create our gooddata dashboard. After initializing the gooddata dashboard, I am not sure how the endpoints can help us. Here is the code
Copy code
const script = this.renderer.createElement('script');
				const head = this.renderer.selectRootElement('head', true);
				const gdElement = document.createElement('gd-dashboard');

				script.type = 'module';
				script.id = 'customDashScript';

				// Create the script content with imports and context setup
				script.textContent = `
					import { setContext } from "<https://innerspace.cloud.gooddata.com/components/${workspaceId}.js>";
					import { tigerFactory, TigerTokenAuthProvider } from "<https://innerspace.cloud.gooddata.com/components/tigerBackend.js>";

					try {
						setContext({
						backend: tigerFactory()
							.onHostname("<https://innerspace.cloud.gooddata.com>")
							.withAuthentication(new TigerTokenAuthProvider("${token}")),
						workspaceId: "${workspaceId}",
					});
					} catch(e) {
						// console.log('Context set');
					}
				`;

				// Append script to head
				this.renderer.appendChild(head, script);

				gdElement.classList.add('dashboard');
				gdElement.id = 'gdElement'
				gdElement.setAttribute('dashboard', this.dashboardId);
				gdElement.addEventListener(INITIALIZED, this.onDashboardLoaded.bind(this));
				gdElement.addEventListener('GDC.DASH/EVT.INITIALIZED', () => {
					console.log('Dashboard initialized — now pushing filters');
					setTimeout(() => {
						this.pushFilters(gdElement);
					}, 10000);
				});
				// gdElement.addEventListener(DATE_FILTER_CHANGED, () => {
				// 	debugger
				// });
				gdElement.addEventListener(FILTER_CHANGED, this.onDashboardFilterChange.bind(this));
				gdElement.addEventListener(DATE_FILTER_CHANGED, this.onDashboardFilterChange.bind(this));

				window.addEventListener('message', (event: MessageEvent) => {
					const data = event.data?.gdc?.event;

					if (!data?.name) return;

					if (data.name === "GDC.DASH/EVT.FILTER_CONTEXT.ATTRIBUTE_FILTER.SELECTION_CHANGED") {
						debugger
						console.log("Filter Changed:", data);

						/** 🔥 Store updated filters for reuse later */
						this.dashboardFilters = data.data?.filters ?? [];

						console.log("Stored Filters:", this.dashboardFilters);
					}
				});

				if (document.getElementById('dashboardContainer')) {
					document.getElementById('dashboardContainer').innerHTML = '';
					document.getElementById('dashboardContainer').appendChild(gdElement);

					setTimeout(() => {
						this.gdDashboardLoading$.next(false);
						this.dashboardConfigured.set(true);
					}, 1000);
				} else {
					this.gdDashboardLoading$.next(false);
					this.dashboardConfigured.set(false);
				}
👀 1
s
Hi @Fardim Kaiser I will take a look into your code and get back to you ASAP
❤️ 1
gratitude thank you 1