Part 2: Adding properties to the visualization

In part 1 of this tutorial, we added a palette property for the colors of the scatter points. In part 2 we will add some more properties to the visualization like a title, point shape, x- and y maximum, and show title flag. We will see various options for defining a property, like a default value and the allowNull flag, and property groups.

Before you start

Make sure you have completed Part 1: Creating a custom visualization or you have downloaded the source code for part 1.

Step 1: Modify the vizdef.xml file

We already saw that property definitions are part of the vizdef.xml file. In this step we will not only add properties, but we also organise the properties in property groups.

Property groups are a hierarchical organisation of properties. The host application will often show property groups as separate tabs or panels in the UI. Placing a property of your custom visualization in a group will make the property appear in the corresponding place in the UI.

For the scatter visualization, we want to define the following properties structure:

  • visualization (group)
    • general (group)
      • color - palette property that we added in step 1 of part 1.
      • pointShape - shape of a scatter point, ("circle" or "square").
      • background - url to a background image.
      • showBackground - flag that indicates whether the background should be displayed.
    • axis (group)
      • xmax - maximum value on x-axis, or null for automatic.
      • ymax - maximum value on y-axis, or null for automatic.

The vizdef.xml entries for these properties look as follows:

<properties>
    <group name="general">
        <palette name="color" slot="categories" />
        <enum name="pointShape" defaultValue="circle">
            <possibleValue>circle</possibleValue>
            <possibleValue>square</possibleValue>
        </enum>
        <string name="background" defaultValue="" />
        <boolean name="showBackground" defaultValue="true" />
    </group>
    <group name="axis">
        <number name="xmax" allowNull="true" />
        <number name="ymax" allowNull="true" />
    </group>
</properties>

Two attributes to notice here are defaultValue and allowNull. The defaultValueattribute represents the initial value that the property will get. The allowNull attribute indicate if null values for the property are allowed. By default, null values are not allowed. For your custom visualization code this means in the default situation you can always rely on a non-null value when calling Properties.get.

Step 2: Add code in Main.ts

pointShape

Changing the shape of a point is easy enough, since for each possible enum value there is a corresponding d3 symbol type available. Replace the current code that determines the palette and shape to:

// Determine color palette and shape from the properties.
const palette = props.get( "color" );
const shape = d3.symbol().size( 256 );
if ( props.get( "pointShape" ) === "square" )
    shape.type( d3.symbolSquare );
else
    shape.type( d3.symbolCircle );

If you want to support more that just these two shape types, feel free to extend this code a bit more. Maybe you want to use a switch statement to select the correct symbol type, or use a lookup map.

Notice that the value of an enum property is always a string. We can safely compare the property value with the literal string "square", or we can use the value of the property in a switch statement.

Note: It is good practice to choose enum values that are not likely to change over time. In Part 3 of this tutorial we will learn how to add a localized 'caption' for an enum value, that is used for showing in the UI.

xmax and ymax

In part 1 we already defined the domain for our axes by calling getDomain on the data. If xmax or ymax are non-null, we can use these property values instead. So the code to create the y-axis should be changed as follows:

Line Code
1
2
3
4
5
6
7
8
9
10
11
// Create the y-axis.
const yHeight = _info.node.clientHeight - 2 * margin - xHeight;
const yDomain = data.cols[ YPOS ].domain.asArray(); // [min, max]
const yMax = props.get( "ymax" );
if ( yMax !== null )
    yDomain[ 1 ] = yMax;
const yScale = d3.scaleLinear().range( [ yHeight, 0 ] ).domain( yDomain );
if ( yMax === null )
    yScale.nice(); // apply nice scale only if scale is automatic.
const yAxis = svg.select<SVGGElement>( ".yaxis" ).call( d3.axisLeft( yScale ) );
const yWidth = yAxis.node().getBBox().width;

The call to props.get( "ymax" ) on line 4 will return either null or a valid number. This is because allowNull = true was set on the property.

The code change for the x-axis is now trivial:

Line Code
1
2
3
4
5
6
7
8
9
10
11
// Create the x-axis and position at bottom of y-axis.
const xWidth = _info.node.clientWidth - yWidth - 2 * margin;
const xDomain = data.cols[ XPOS ].domain.asArray(); // [min, max]
const xMax = props.get( "xmax" );
if ( xMax !== null )
    xDomain[ 1 ] = xMax;
const xScale = d3.scaleLinear().range( [ 0, xWidth ] ).domain( xDomain );
if ( xMax === null )
    xScale.nice(); // apply nice scale only if scale is automatic.
const xAxis = svg.select<SVGGElement>( ".xaxis" ).call( d3.axisBottom( xScale ) );
xAxis.attr( "transform", `translate(0,${yHeight})` );

background and showBackground

To add a background to the scatter visualization, we add the following code to the updatemethods, just before you create the y-axis:

Line Code
1
2
3
4
5
6
7
8
9
10
11
12
// Set the background image.
let urlImage = null;
if ( props.get( "showBackground" ) )
{
    const image = props.get( "background" );
    if ( image !== "" )
        urlImage = `url(${image})`;
}
_info.node.parentElement.style.backgroundImage = urlImage;

// Create the y-axis.
...

This code changes the backgroundImage style of the parent element of the svg. The parent of the svg is actually the _node that was passed to us in create.

Step 3: Run and test the visualization

Create a new dashboard or report in IBM® Cognos Analytics and add the 'Preview Visualization'. After adding some data you should see the scatter visualization in action. Try changing some of the properties that we have just added. You will see that the properties have been added to the visualization tab and the text tab respectively.

Links