Manipulate viewers
Viewers are main visual components of the Datagrok platform. Our JavaScript API exposes functionality for manipulating native viewers, such as scatter plot or histogram, as well as for developing custom viewers.
Table of contents:
Adding viewers to table views
There are several options for attaching a viewer instance to your layout. First of all, you can add it directly to a table view:
let data = grok.data.demo.demog();
let view = grok.shell.addTableView(data);
view.addViewer('Histogram', { value: 'age' });
To avoid hardcoding the name of a viewer, you can reach it from the DG
namespace, e.g., DG.VIEWER.HISTOGRAM
or DG.VIEWER.PIE_CHART
. For native viewers, Datagrok's API provides a bunch of handy wrapper methods, so this code
snippet is equivalent to the one given above:
let data = grok.data.demo.demog();
let view = grok.shell.addTableView(data);
view.histogram({ value: 'age' });
In both cases, the options
parameter is not required, besides, it is possible to specify them later on with the
viewer's setOptions method. The addViewer
method differs in that it can be used with all viewers, both native and custom-built ones:
view.addViewer('Leaflet').setOptions({
latitudeColumnName: 'lat',
longitudeColumnName: 'lng',
renderType: 'heat map'
});
Another way to add a viewer starts with creating it by viewer type:
let data = grok.data.demo.demog();
let view = grok.shell.addTableView(data);
let viewer = DG.Viewer.fromType(DG.VIEWER.LINE_CHART, data);
view.addViewer(viewer);
Notice that the first parameter to addViewer
may be either a string with the corresponding name or an instance of
the Viewer
class.
A dataframe on which the view is built has handy plotting methods of its own:
let data = grok.data.demo.demog();
let view = grok.shell.addTableView(data);
let viewer = data.plot.scatter({ x: 'weight', y: 'height', color: 'disease' });
view.addViewer(viewer);
There is a slight difference between native and custom viewers. DG.Viewer.fromType
is reserved for the standard viewer
types. When creating an instance of the custom one, use DataFrame.plot.fromType
instead. Instances of JsViewer
's subclass are obtained asynchronously on the client, as their package should be
initialized first. As a rule of thumb, you should wait until a JsViewer object is constructed. However, if your plans
are limited to adding it to a table view without further adjustments, a synchronous call of addViewer
will do (
use setOptions
to specify property values, but have in mind that its success depends on your viewer's implementation,
and the application of supplied values is not guaranteed in synchronous use).
Examples:
- Bar Chart
- Markup
- Box Plot
- Matrix Plot
- Calendar
- Network Diagram
- Correlation Plot
- PC Plot
- Density Plot
- Pie Chart
- Filters
- Scatter Plot
- Form Viewer
- 3D Scatter Plot
- Globe Viewer
- Shape Map
- Google Map
- Statistics
- Grid
- Tile Viewer
- Heat Map
- Tree Map
- Histogram
- Trellis Plot
- Line Chart
- Word Cloud
Working with properties
An essential part of working with visualizations is to customize their appearance. As we have seen, our JavaScript API provides multiple methods for this purpose. Let's now have a look at how to find out what properties a particular viewer exposes and what information you can derive from them.
First, the setOptions
method has a counterpart getOptions
, which returns serialized viewer options. It takes a flag
specifying whether the properties with the defaults values should be returned. Not including default properties makes it
more clean and efficient for serialization purposes, so it is set to false
by default:
let data = grok.data.demo.demog();
let view = grok.shell.addTableView(data);
grok.shell.info(view.grid.getOptions(true));
If you run this code, the options of the grid viewer will be in the look
field of the returned object. There is also
an easier and more user-friendly way to get a list of needed properties. If the platform instance you are working on
happens to have the
DevTools package installed, simply open your
dataset, add a viewer to it, tweak the settings as they fit, and right-click to reach the viewer's context menu. There
you can choose the command To JavaScript
to get a snippet that adds an identical viewer to the current view. Another
UI-first approach is to save the layout of a table view along with its viewers and their positions. Find more detailed
instructions on the dedicated page.
However, in some cases you may want to derive more details about certain viewer properties. To access them directly, use
the getProperties
method:
let data = grok.data.demo.demog();
let view = grok.shell.addTableView(data);
let bc = view.barChart();
let descriptions = bc.getProperties()
.map((p) => p.propertyType + ' ' + p.name + ': ' + p.description + ' ' + p.columnFilter)
.join('<br>');
grok.shell.info(descriptions);
It returns an array of Property
objects, which are used to construct descriptions. Here is what you can obtain given a
property:
choices
: an array of predefined values that a property accepts, e.g., all possible aggregation functions you can use for theValue
column in a bar chart; choices are given in a drop-down list in the context panelcolumnFilter
: an indication of allowed data types, it is only relevant to column properties, e.g., theValue
column of a box plot has a numerical filter; acceptable values are numerical , categorical, and an individual data type (useDG.COLUMN_TYPE
to refer to it)defaultValue
: a value used by default, often coupled with choices (and should be among the array values for choices if you are developing a custom viewer)propertyType
: the type of property values, e.g., margins and colors in a grid expectint
valuessemType
: the semantic type of a data property, it is used by cell renderers to plot column values according to the nature of the data (for the semantic typeMolecule
strings are rendered as chemical structures)
Examples:
- Inspect viewer properties
- Get access to canvas and column selectors
- Customize scatter plot rendering
Adding viewers to views
You can add a viewer to any container, such as a main application view or a dialog window.
Here is how to create a new view and add a plot to it:
let v = DG.Viewer.scatterPlot(grok.data.demo.demog());
grok.shell.newView('foo').append(v.root);
Here is an example of adding controls and viewers to a dialog box:
ui.dialog()
.add(ui.div([
"Here's a plot in the dialog",
DG.Viewer.scatterPlot(table)
]))
.show();
Check the ChaRPy package for a similar example.
Docking viewers
Just like other visual components that occupy a window of their own, viewers can be docked to a particular position:
let data = grok.data.demo.demog();
let view = grok.shell.addTableView(data);
let viewer = DG.Viewer.fromType(DG.VIEWER.SCATTER_PLOT, data);
view.addViewer(viewer);
view.dockManager.dock(viewer, 'right');
The list of positions consists of the following options: left | right | top | down | fill
. You can refer to them from
the DG
namespace, e.g., DG.DOCK_TYPE.RIGHT
. Notice that here the viewer will be placed independently of the table
view:
grok.shell.dockManager.dock(viewer, DG.DOCK_TYPE.RIGHT);
Examples:
Custom viewer initialization
Some viewers can require additional initialization actions such as rendering something on top of the viewer, setting some options based on additional computations and so on. A good example is an Activity cliffs analysis, which draw lines, adds additional information and buttons on top of the scatter plot.
To add custom such initialization to your viewer:
- create your function which takes
DG.Viewer
as an argument and performs all custom actions with the viewer. - pass the name of the function as a
initializationFunction
parameter when creating the viewer.
And that's it! Now you can save layouts and projects with your viewer. Custom initializationFunction
will run every time when you create the viewer including restore from projects or layouts.
Example
// Custom viewer initialization function.
// Using this approach, you can attach behavior to functions that could be saved in the layout, etc.
// For JS-based initialization, see init-script.js
// This function is dynamically registered for the sake of simplicity.
// Normally, you would use a package function
grok.functions.register({
signature: 'void initScatterSquare(viewer v)',
run: (v) => {
v.onAfterDrawScene.subscribe((_) => {
v.canvas.getContext('2d')
.setFillStyle('red')
.fillRect(100, 100, 50, 50);
});
}
});
grok.shell
.addTableView(grok.data.demo.demog())
.scatterPlot({ initializationFunction: 'initScatterSquare' });
See also: