Skip to main content

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:

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.

Get a snippet with selected viewer properties

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 the Value column in a bar chart; choices are given in a drop-down list in the context panel
  • columnFilter: an indication of allowed data types, it is only relevant to column properties, e.g., the Value column of a box plot has a numerical filter; acceptable values are numerical , categorical, and an individual data type (use DG.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 expect int values
  • semType: 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 type Molecule strings are rendered as chemical structures)

Examples:

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: