Skip to main content
Announcements
Qlik Community Office Hours, March 20th. Former Talend Community users, ask your questions live. SIGN UP
cancel
Showing results for 
Search instead for 
Did you mean: 
Not applicable

Applying selections to d3 Extension Chart

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...

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

1 Solution

Accepted Solutions
Not applicable
Author

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

View solution in original post

7 Replies
ErikWetterberg

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

Not applicable
Author

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

ErikWetterberg

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

Not applicable
Author

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?

Not applicable
Author

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

Rohith_1914
Contributor
Contributor

Hi i was implementing selection to my custom extension and i am getting few errors regarding backendapi. It show's backendapi is undefined and Cannot read property 'selectValues' of undefined. Help me in resolving this issue

sushant_agarwal29
Contributor
Contributor

Hi Rohith,

Did you find solution to this problem yet, I am also facing similar issue with this implementation.