Now that we have our visualization working in Qlik Sense, let's inject Qlik's data in there. After increasing our max/min number of measures and creating a new object, we can add any measure we want, it could be a count, sum, average, of the selected data field. For simplicity, we can add our own number such as "=90" as a measure. We'll start by checking out the measure we just added in the hypercube in layout:

Inside layout, we have our extension's qHypercube, that includes the selected data input to the extension, the dimension and measures' labels as well as metadata. The data is divided in data pages. In this extension, we're using only one data page, the initial data page we pulled near the top of our code, Inside each data page in qDataPages is a qMatrix and some metadata about it, such as the number of rows and columns included in this data page. Inside our qMatrix is all the individual rows in the data page. Inside each row, is all the column values for this row. And finally, inside each of these column values is a qNum, a numeric version of the value, and a qText, a textual version of the value. Note that the column values are not defined as a dimension or a measure, it is up to us to use the qText for dimensions and qNums for measures. If we would use the qText of a measure, we would be retrieving the formatted version of the value (for instance 2 decimal places) while the qNum value itself could include many more.

So, we'll start by defining the path to our qMatrix and the data itself (one measure in this case) in variables, so we'll be adding this code snippet to the end of our paint function:

var qMatrix = layout.qHyperCube.qDataPages[0].qMatrix;

var data = qMatrix.map(function(d) {

return {

"Metric1":d[0].qNum

}

});

Now that we have our data ready, let's prepare our extension to receive our data. We'll start by adding more parameters to our function to get access to the data, layout, and the width/height of the object. We'll create a kpi variable that maps to our measure's data in the data variable. Width and height are currently hardcoded in pixels in the first block of code so we'll use the width/height parameters we just added to make the size of the visualization dynamic.

var vizwithoutref = function(data,layout,width,height,id) {

var kpi = data.map(function(d){return d.Metric1;});

var svg = d3.select("#" + id)

.append("svg")

.attr("width", width)

.attr("height", height);

var gauge = iopctrl.arcslider()

.radius(120)

.events(false)

.indicator(iopctrl.defaultGaugeIndicator);

gauge.axis().orient("in")

.normalize(true)

.ticks(12)

.tickSubdivide(3)

.tickSize(10, 8, 10)

.tickPadding(5)

.scale(d3.scale.linear()

.domain([0, 160])

.range([-3*Math.PI/4, 3*Math.PI/4]));

var segDisplay = iopctrl.segdisplay()

.width(80)

.digitCount(6)

.negative(false)

.decimals(0);

svg.append("g")

.attr("class", "segdisplay")

.attr("transform", "translate(130, 200)")

.call(segDisplay);

svg.append("g")

.attr("class", "gauge")

.call(gauge);

segDisplay.value(kpi);

gauge.value(kpi);

}

Don't forget to actually give the function these parameters by adding them in the function call:

vizwithoutref(data,layout,width,height,id);

Now we can go to Qlik Sense, open DevTools, and refresh the page using F5, change our measure to "=30", and watch our speedometer change from 90 (that we set earlier) to 30.

In order to size the gauge itself correctly however, we could either create a formula that dynamically sizes it based on the width and height, or create a sizing map where we size it a certain way if it's between a certain set of heights and a certain set of widths. In our example, we'll be using a sizing map to keep things clean. If we had gone the formula route, we'd have a hard time finding a formula that fits all kinds of width/height combinations. Since the gauge is circular, we'll be checking if the width or height is shorter and draw the circle's radius using that factor. Once we're done drawing out our sizing map, we can add its variables in the place of hardcoded variables, such as the gauge's radius, gauge's tickPadding, the segDisplay's width, and both the segDisplay and the gauge's tranform statement that tells the D3 library where to paint them in our visualization. Here is our resizable function with the sizing map and the changes in the D3 code:

Now that we've identified the variables in the D3 code that affect the resizing of the visualization, and changed them from being hardcoded to a dynamic variable that we can control, we can go to our app to test the resizing:

In the next section, we’ll be modifying the D3 code to add another gauge indicator for a reference line, as well as edit the CSS file for styling our visualization.

I have been following along with this tutorial up until the point of the qmatrix and have hit a wall. I copied into my java script everything you have up through changing the call script to vizwithoutref(data,layout,width,height,id);

When I open the visualization in Qlik Sense, I am not given an option to edit the measure ="30" (You can see that the measures section is grayed out. I am also attaching my java script file. Please let me know what I am doing wrong. I think it has to do with the calling of my qmatrix variable placement.

Thanks for following along. Unfortunately, I can't seem to download the file you linked on dropbox, possibly because you moved the file later? If you can send another link to the file, I can certainly check it out.

One of the things you should check is the initialproperties near the top of the javascript file. If the properties of max measures and min measures are set to 0, that would be the problem:

//paint is the function that gets called every time the //variables or selection changes, or if you resize the window. paint : function($element,layout) { //element is what holds the chart's width and length //layout is what holds Qlik's dimensions and measures as well as //the custom settings selected

//Pushing element and layout to the console for //reference-finding and debugging console.log($element); console.log(layout);