Question T9564
Visible to All Users

VisualizationPanel UpdateData explanations

created 3 years ago (modified 3 years ago)

Hi Guys,

how does UpdateData works?

I'm passing data to update analitycs visualization panel generated with "PollVisualizer example" (https://surveyjs.io/Examples/Analytics?id=custom-poll-vis&platform=Reactjs&theme=defaultV2), however calling this method, panel is not updating; my goal is to update data part only every "x" seconds.

1- Should i call the refresh method?
2- If yes, refresh method updates the whole component, is there a way to update only the given part data?

Thanks in advance

Answers approved by surveyjs Support

created 3 years ago

Hello,

The updateData method actually leads to set data for a DataProvider object https://github.com/surveyjs/survey-analytics/blob/master/src/dataProvider.ts#L56 which leads to onDataChanged event fire https://github.com/surveyjs/survey-analytics/blob/c540ef9f2b3cfff3d8c0279a7d6cf0184b17bd8f/src/dataProvider.ts#L209. Right now this event may not to trigger visualizer re-rendering (it depends on the survey structure). DataProvider is shared between all visualizers inside a panel to provide cross-items filtering capability.

So, in short - you need to call the "refresh" method to re-render visualizer;

If you share your scenario in greater details (as a minimal live example) - probably we could give you more certain recommendations.

Thanks, Serge
SurveyJS Team

    Comments (3)

      Here's my scenario:
      First the method for rendering analytics

      TypeScript
      renderAnalytics() { //Custom visualizer for poll results function PollVisualizer(question, data) { var renderContent = function (contentContainer, visualizer) { var answersData = visualizer.getAnswersData(); var datasets = answersData.datasets; var labels = answersData.labels; var colors = answersData.colors; var texts = answersData.texts; var seriesLabels = answersData.seriesLabels; var hasSeries = seriesLabels.length > 1; var emptyTextNode = (SurveyAnalytics as any) .DocumentHelper .createElement("p", "", { innerHTML: SurveyAnalytics .localization .getString("noResults") }); if (datasets.length === 0 || datasets[0].length === 0) { contentContainer.appendChild(emptyTextNode); return; } datasets.forEach(function (data, idx) { var tableNode = ((SurveyAnalytics as any).DocumentHelper.createElement("table", "sa-poll-table")); tableNode.style.backgroundColor = visualizer.backgroundColor; data.forEach(function (rowData, index) { var row = (SurveyAnalytics as any) .DocumentHelper .createElement("tr"); var labelCell = (SurveyAnalytics as any) .DocumentHelper .createElement("td", "sa-poll-table__cell", { textContent: labels[index] + " - " + texts[idx][index] + "%" + " (" + rowData + " voti)", }); row.appendChild(labelCell); tableNode.appendChild(row); row = (SurveyAnalytics as any) .DocumentHelper .createElement("tr"); var sparklineCell = (SurveyAnalytics as any) .DocumentHelper .createElement("td", "sa-poll-table__cell"); sparklineCell.colspan = "3"; var outerBar = (SurveyAnalytics as any) .DocumentHelper .createElement("div", "sa-poll-sparkline"); var innerBar = (SurveyAnalytics as any) .DocumentHelper .createElement("div", "sa-poll-sparkline-value"); innerBar.style.width = texts[idx][index] + "%"; outerBar.appendChild(innerBar); sparklineCell.appendChild(outerBar); row.appendChild(sparklineCell); tableNode.appendChild(row); }); contentContainer.appendChild(tableNode); }); }; var visualizer = new SurveyAnalytics.SelectBase(question, data, { renderContent: renderContent }, "pollVisualizer"); visualizer.answersOrder = "asc"; visualizer.showPercentages = true; return visualizer; } //Unregister default radiogroup visualizer SurveyAnalytics .VisualizationManager .unregisterVisualizer("radiogroup", SurveyAnalytics.SelectBasePlotly); // Register custom visualizer for the given question type SurveyAnalytics .VisualizationManager .registerVisualizer("radiogroup", (PollVisualizer as any)); SurveyAnalytics.VisualizationManager.unregisterVisualizerForAll(SurveyAnalytics.WordCloud); SurveyAnalytics .localization .locales["en"] = new AnalyticsTranslation(); // Set localized title of this visualizer SurveyAnalytics.localization.locales["en"]["visualizer_pollVisualizer"] = "Poll visualizer"; var survey = new Survey.Model(this.sondaggio.ObjectJsonDefinizione); var options: SurveyAnalytics.IVisualizationPanelOptions = { haveCommercialLicense: true, //Add this line // survey: survey, allowDynamicLayout: false, allowHideQuestions: false }; this.visPanel = new SurveyAnalytics.VisualizationPanel(survey.getAllQuestions(), this.risposteSondaggio, options); this.visPanel.showHeader = true; var surveyResultNode = document.getElementById("surveyResult"); surveyResultNode.innerHTML = ""; this.visPanel.render(surveyResultNode); }

      Then the method for fetching and updating data on analytics:

      TypeScript
      getRisposteSondaggio() { if (this.subscription != null && !this.subscription.closed) this.subscription.unsubscribe(); var observable = this.sondaggioService.getRisposte(this.sondaggio); //Se il sondaggio è attivo ripeto continuo a leggere le risposte e aggiornare il sondaggio if (this.sondaggio.IsAttivo) { observable = this.sondaggioService.getRisposte(this.sondaggio).pipe(repeat({ delay: 2000 })); } this.subscription = observable.subscribe({ next: res => { if (!res.isErrore) { this.risposteSondaggio = res.risultato; if (res.risultato) { this.risposteTotali = res.risultato.length; } if (!this.visPanel) { this.renderAnalytics(); } else { this.visPanel.refresh(); } } else { let title = this.translateService.instant("globals.attenzione"); this.interfaceService.showError(title, res.errore.error); } }, complete: () => { }, error: error => { let title = this.translateService.instant("globals.attenzione"); this.interfaceService.showError(title, error); this.interfaceService.closeLoading(); } }) }

      I would like to replace the refresh method that redraws the entire component without maintaining its state by implementing a solution that would allow me to do so by updating only the data part.

        Hello,

        Thank you for the clarifications. This task is in my task list. I'll update this thread as soon as I'll have any results.

        Thanks, Serge
        SurveyJS Team

          Hello,

          Your approach looks ok for me. Probably you need to pass a new data to visualizers before this.visPanel.refresh(); call.

          Thanks, Serge
          SurveyJS Team