In the quickstart we had a dashboard with a table and a few charts. Often, that is not enough. We need an interactive way to filter through data. This tutorials deals with adding such interactivity with Gramex.
The chart in the quickstart displayed a single view for the complete dataset - with no way to filter the data or change the chart dynamically.
By the end of this tutorial, you will have learnt to:
The application you have at the end of the quickstart should look like this.
This tutorial assumes that you have gone through the quickstart and have successfully built the Gramex application and created these files:
The FormHandler
component is Gramex’s primary data model.
Think of FormHandler as ‘SQL over HTTP’. If data
is our typical data endpoint, then data?Segment=Consumer
returns only those rows which have “Consumer” in the “Segment” column.
Check out the list of possible operations in the
formhandler documentation.
Add the formhandler table to the page as follows:
<link rel="stylesheet" href="../ui/bootstraptheme.css" />
<div
class="formhandler"
data-src="../data?_c=-Ship Date&_c=-Order Date&_c=-Order ID&_c=-Ship Mode&_c=-Quantity&_c=-Discount"
></div>
<script src="../ui/jquery/dist/jquery.min.js"></script>
<script src="../ui/bootstrap5/dist/js/bootstrap.bundle.min.js"></script>
<script src="../ui/lodash/lodash.min.js"></script>
<script src="../ui/g1/dist/g1.min.js"></script>
<script>
$(".formhandler").formhandler({ pageSize: 5 });
</script>
Any interaction with the table changes the URL hash. By storing the state of interactions in the URL, we can capture a particular view of the data, just by capturing the URL. g1 provides a way to listen to URL changes via urlchange.
<script>
$(window)
.on("#?", function (e) {
console.log(e.change);
})
.urlchange();
</script>
Here, we are logging URL hash changes in the console whenever they happen. Generally, any function can be run when the url change event is triggered.
After you save the file and refresh the browser, open up the browser console. Now, whenever you interact with the g1 table, you should see the URL hash printed in the console.
Now all we have to do is to change the console logging action to something that redraws the existing charts with the new data present in the FormHandler table. Recollect that we had the following specification for our charts, followed by a function to render them.
<script>
var spec = {
$schema: "https://vega.github.io/schema/vega-lite/v3.json",
description: "A bar chart that sorts the y-values by the x-values.",
width: 360,
height: 200,
data: { url: "data?_by=Segment" },
mark: "bar",
encoding: {
y: {
field: "Segment",
type: "nominal",
sort: { encoding: "x" },
axis: { title: "Segment" },
},
x: {
field: "Sales|sum",
type: "quantitative",
},
},
};
function render_charts(chartid, xfield) {
spec.encoding.x.field = xfield;
var view = new vega.View(vega.parse(vl.compile(spec).spec))
.renderer("svg")
.initialize(chartid)
.hover()
.run();
}
</script>
Note that the chart gets its data from the data.url
attribute enclosed in the spec:
{ "data": { "url": "data?_by=Segment" } }
Therefore, we need to grab the changed URL hash, and set spec.data.url
to the changed
URL.Add the following function which grabs the changed URL, sets the data.url
attribute of the spect to the new URL, and redraws the charts.
function draw_charts(e) {
spec.data.url = "data?" + e.hash.search + "&_by=Segment";
render_charts("#chart1", "Sales|sum");
render_charts("#chart2", "Quantity|sum");
}
Finally, we must remember to remove the earlier URL change listener (which simply logged changes to the console), and add our new function as the listener.
The changed event listener should look like:
$(window).on("#?", draw_charts).urlchange();
Save your file and reload the page. As you click on any value in the table,
the charts will redraw based on the applied filter. As a special case of this, try filtering the
Segment
column by some value (by clicking on any value in that column) - you should see that
both the bar charts contain only one bar.
Try comparing the order quantities and the sales in the state of Florida across the three segments
(you can do this by selecting Florida under the State
column), and you should see that while the
Corporate and the Consumer segments place a nearly equal number of orders in Florida, the Corporate
segment has only about two thirds the total sales of the Consumer segment.