Registering Behaviours

In this section, we will learn how we can register a set of behaviours to get custom interactions in the canvas. When registering behaviours, they can be dispatched either by mapping them with a physical action or directly dispatching them. Any side effects that will be mapped to these behaviours will be applied automatically.

We will be using the cars.json data to understand how to register behaviours.

How do you register a behaviour?

In order to register a behaviour, we will use the standard classes provided for Behaviours by Muze. Let us understand how this works with a simple example.

For instance, the normal select behaviour retains all the selections. We will register a SingleSelectBehaviour that will always only select one and only one mark in the plot( be it a bar or a point). This way, it will not retain the selections made every time this behaviour is called.

Getting the base class and the Action Model

In order to add a behaviour, we need to use the base class provided by Muze. This base class contains the properties required for us to add a behaviour. To get it, we call the GenericBehaviour class from muze.Behaviours.standards :

const GenericBehaviour = muze.Behaviours.standards.GenericBehaviour

We also need the ActionModel which handles the interaction model between the canvases

const ActionModel = muze.ActionModel

Using the base class to create a new behaviour

To register an action we will create a new class that will be inherited from the GenericBehaviour class. We will use the registerBehaviouralActions method provided by the ActionModel for this:

ActionModel
    .for(canvas)
    .registerBehaviouralActions([class SingleSelectBehaviour extends GenericBehaviour {
          static formalName() {
              return 'singleSelect';
          }
}])

As you can see, we have registered a behavioural action by declaring a new class: SingleSelectBehaviour which is a subclass of the GenericBehaviour class. We also have to provide a formal name to the class, which we have given here as singleSelect.

This formal name is very important as this is what identifies this behaviour.

Adding Behavioural Properties

Recall, the objective of a behaviour is to set the selection and rejection sets, which together form the complete set. The setSelectionSet method provides the necessary information to the set this information.

Once we have declared the class with the formal name, we will use the setSelectionSet method to set the selection and rejection sets. Here, we get the addSet and selectionSet (which is information about the complete set).

The addSet consists of the set of rows that have been newly interacted with. This should essentially form the new entry set. The selectionSet consists of the information about the complete set and hence contains all the rows of the DataModel with their selection and rejection information.

In order to change the selection and rejection sets, Muze provides some properties for the selectionSet. Updating this set automatically updates the rejection set(since, the rejection set is the set of rows not present in the complete set, there is no need to store it separately. Only the entry and exit sets are stored). Following are the set of methods provided:

  • add(set): Updates the selection set. It adds the new entries to the New Entry Set and updates the Old Entry Set. Consequently, also adds the elements not in the selection set to the Exit Set

  • remove(set): Updates the rejection set. It adds the new entries to the New Exit Set and updates the Old Exit Set. Consequently, also adds the elements not in the rejection set to the Entry Set

  • reset(): Resets the selection and rejection sets making them empty

  • updateEntry(): Updates the selection set by pushing already present entries to the Old Entry Set

  • updateExit(): Updates the rejection set by pushing already present entries to the Old Exit Set

  • getSets(): Gets the details of all the sets present

Let's look at the code for the SingleSelectBehaviour's setSelectionSet method:

setSelectionSet (addSet, selectionSet) {
    selectionSet.reset();
    selectionSet.add(addSet);
    return selectionSet;
}

In order to apply single selection on the canvas, we have to remove the existing selection set(i.e., the previous selection) and add the new entries to the selection set. Let's break the code down to get a deeper understanding of what we have done here:

Resetting the add set:

Our first step is to reset the selection set if no selections are made. This brings the selection set to the empty condition and This removes all the elements from all the Entry and Exit sets

selectionSet.reset();       // Resetting the selection set to empty

Updating the entry set:

We will reset the selection set first to empty since only new entries are needed for single select. Otherwise, we will add the new elements to the New Entry Set.

selectionSet.reset(); /* empty selection */
selectionSet.add(addSet); /* add new entries to the new entry set */

It is to note that registering a behaviour is not enough. It is also necessary to map them to a trigger(physical action or dynamic dispatch) and map a side effect with them. The code, along with the resultant behaviour can be found below.

main
run-button
run-button
reset-button
        canvas
          .width(600)
          .height(400)
          .rows(['Horsepower'])
          .columns(['Origin'])
          .data(dataModelInstance)
          .mount(node);
        ActionModel
          .for(canvas)
          .registerBehaviouralActions([class SingleSelectBehaviour extends GenericBehaviour {
            static formalName () {
              return 'singleSelect';
            }
            setSelectionSet (addSet, selectionSet) {
      
              if (addSet === null || !addSet.length) {
                selectionSet.reset();
              } else {
                  selectionSet.reset();
                  selectionSet.add(addSet);
              }
            }
      }]);

Wrapping Up

In this section, we got a basic understanding of how to register behaviours. To summarize

  • The main objective of a behavioural action is to create the selection and rejection sets
  • You can create your own behaviour by extending the GenericBehaviour class available from Muze
  • Every registered behaviour must have a formal name
  • The setSelectionSet method accepts an addSet and a selectionSet to form the selection and rejection sets.