5 Replies Latest reply: Aug 17, 2017 7:04 AM by Thorben Ortmann RSS

    Applying selections to d3 Extension Chart

    Thorben Ortmann

      Hi there,

       

      I am on my way to integrate several d3 (https://d3js.org/) charts via Extensions into Qlik Sense.

      So far I achieved  to get the data out of Qlik Sense (respectively from qMatrix in the hypercube)  and fill my d3 Extension with it, so that I can see the data visualized in the Extension already (great Tutorial here:http://www.axisgroup.com/tutorial-how-to-build-a-qlik-sense-extension-with-d3/).

      Next I want to enable the user to make selections in the Extension. In the developers help I found this entry regarding selections:http://help.qlik.com/en-US/sense-developer/June2017/Subsystems/Extensions/Content/Overview/selection-models.htm

       

      As far as I understand this:

      return { initialProperties : { version: 1.0, qListObjectDef : { qShowAlternatives : true, qFrequencyMode : "V", qInitialDataFetch : [{ qWidth : 2, qHeight : 50 }] }, fixed : true, width : 25, percent : true, selectionMode : "CONFIRM" },


      is just important to define which selectionMode should be used.

       

      and this:

      if(this.selectionsEnabled && layout.selectionMode !== "NO") {

          $element.find('li').on('qv-activate', function() {

                if(this.hasAttribute("data-value")) {

                      var value = parseInt(this.getAttribute("data-value"), 10), dim = 0;

                    if(layout.selectionMode === "CONFIRM") {

                          self.selectValues(dim, [value], true);

                          $(this).toggleClass("selected");

                    } else {

                          self.backendApi.selectValues(dim, [value], true); } } }); }

       

      first checks if selections are enabled and if that is the case tells the found elements by $element.find('li') to react to the event 'qv-activate' as specified in the anonymous function. After that I am not able to follow completely.

       

      Could someone explain to me how I can make selections work in an d3 extension chart ?

       

      Thanks in advance

        • Re: Applying selections to d3 Extension Chart
          Erik Wetterberg

          Hi,

          No, you don't need to have a selectionmode defined if you don't want the user to be able to select between different modes (which most extensions don't do). There are two different methods to do selections in this code, you can select one of them.

           

          The first one, selectValues defined in the extension (actually in something called DefaultView), will open up the standard confirm dialog and will not repaint the visualization until the confirm dialog closes.

           

          The second one, in the backendApi, will make selections immediately and trigger a repaint. That might be a problem.

           

          The code example uses som jQuery stuff that works for HTML but not SVG (D3 creates SVG), so you will need to replace them. That means that the qv-activate event and the toggle function has to be replaced.

           

          Hope this helps

           

          Erik Wetterberg

            • Re: Applying selections to d3 Extension Chart
              Thorben Ortmann

              Hi,

              first of all thanks a lot for the reply.

               

              Right now I am experimenting with a scatter plot. So the requirement would be that if the user clicks on one of the circles the belonging dimension value gets selected.

               

              With $element.find('circle') I can find all my circles within the svg in the scatter plot

              and with qv-activate (as far as I understand just some kind of onclick-event) I can perform actions if a circle is clicked.

              The code is like this:

               

              var self = this;

              $element.find('circle').on('qv-activate', function() {

                   var value = [1,2], dim = 0;

                   self.selectValues(dim, value, true);

              });

               

              So with this code if I click on a circle in the scatter plot, values [1,2] of the first (and only) dimension in the scatter plot are selected.

              What I need now is:

              - to somehow get the information which circle is clicked (maybe via the event)

              -  depending on that to somehow generate the values for the dimension selection (this information could be saved in the circle-elements i guess)

              - to make deselections possible/ change the selection state

               

              Has someone ideas for that or good sources for reading into this topic? (events, how toggleClass could be replaced...)

               

               

              @Erik Why shouldn't I use 'qv-activate event'? It seems to be working. Is it possible to pass data with this event?


              best regards

              thorben

            • Re: Applying selections to d3 Extension Chart
              Erik Wetterberg

              Hi,

              OK it seems like jQuery works better with svg nowdays, good. Of course you can use qv-activate, but it is undocumented qlik might decide to remove it, in which case your extension will break.

               

              Your event handler will get a parameter with some data around the event, probably something like targetElement. You can use that to know what the user clicked on and as you suggest keep the data in the element.

               

              Hope this helps

               

              Erik Wetterberg

                • Re: Applying selections to d3 Extension Chart
                  Thorben Ortmann

                  Hi,

                  so i gave every circle an index attribute:

                   

                  //Create circles

                  svg.selectAll("circle")

                    .data(dataset)

                    .enter()

                    .append("circle")

                    .attr("cx", function(d) {

                    return xScale(d.Dim1);

                    })

                    .attr("cy", function(d) {

                    return yScale(d.Metric1);

                    })

                    .attr("r", function(d) {

                    return rScale(d.Metric1);

                    })

                  .attr("idx", function(d,i) {

                    return i;

                    });

                   

                  and right now have this code for selecting values:

                   

                  var self = this;

                  $element.find('circle').on('click', function() {

                       var value = [], dim = 0;

                       value.push(parseInt(d3.select(this).attr("idx"),10));

                       self.selectValues(dim, value, true);

                  });

                   

                  With this code it is already possible to select several values per mouseclick.

                   

                  I still wonder about the "qv-activate"event, there has to be some reason qlik help tells us to use this event instead of  the "click" event

                   

                  Now I will have to find ways for deselection and working with and understanding the confirm dialog which appears if you click on the chart.

                   

                  Any ideas for that? Someone?

                    • Re: Applying selections to d3 Extension Chart
                      Thorben Ortmann

                      So here it is:



                      paint: function ($element, layout) {

                       

                              var dataset = layout.qHyperCube.qDataPages[0].qMatrix.map(function(d) {

                                    return {

                                                "Dim1":d[0].qNum,

                                                "Metric1":d[1].qNum,

                                                  "index":d[0].qElemNumber

                                            }

                                });

                      ...

                      ...

                      ...

                      //create circles

                          svg.selectAll("circle")

                            .data(dataset)

                            .enter()

                            .append("circle")

                            .attr("cx", function(d) {

                                  return xScale(d.Dim1);

                                  })

                            .attr("cy", function(d) {

                                  return yScale(d.Metric1);

                                  })

                            .attr("r", function(d) {

                                  return rScale(d.Metric1);

                                  })

                            .attr("idx", function(d) {

                                  return d.index;

                                  });

                       

                          $element.find('circle').on('click', function() {

                                var value = parseInt(d3.select(this).attr("idx"),10), dim = 0;

                                self.selectValues(dim, [value], true);

                          }

                      });

                       

                      So with $element.find('circle') I find all my selectable elements.Then I am attaching a handler for the click-event. After that I get the qElemNumber or idx-attribute of the selected circle to pass this value to self.selectValues().

                       

                      There are still some things to do, however the basic functionality is here, I guess and hope