Data Join-Action

Perform join between Data and Graphical elements

Data Join functionality helps in rendering the elements dynamically with respect to data. It builds a relationship between the data and the graphical elements. I2Djs provides a simple and unique way to define the join.

To begin let's create a data array with 3 items uniquely identified by the id field.

var data = [{id:1, label: 'First'},{id:2, label: 'Second'},{id:3, label:'third'}]

Let's define the join actions for the above data array. The join method takes data, element selector, and action object as an argument. Actions object comprises of joinOn (join key) and actions - enter, update, and exit.

var joinRef = renderer.join(data,'circle',{
                         joinOn:function(d){
                             return d.id;
                         },
                         action:{
                             enter: function(newData){ },
                             exit: function(nodes){ },
                             update: function(nodes) { }
                     }
                });

Enter Action:

Enter method defines an action for the new data. It receives a data object, with elementSelector property holding the corresponding new data array. Since we are performing join with a circle, newData.circle will have the new data array with respect to circle join.

createEls API creates a circle for each data object. In the below example every new circle will be set with attr attributes and style properties. All new circles will be filled with red color.


var joinRef = renderer.join(data,'circle',{
                         joinOn:function(d){
                             return d.id;
                         },
                         action:{
                             enter: function(newData){
                                 this.createEls(newData.circle,{
                                          el:'circle',
                                          attr:{
                                                 x:function(d){return d.id*10},
                                                 y:function(d){return d.id*10},
                                                 r:5
                                          },
                                          style:{
                                                 fill:'#ff0000'
                                          }
                                });
                             },
                             exit: function(nodes){
                             },
                             update: function(nodes) {
                             }
                     }
                })

Update Action:

The Update method defines an action on the nodes of the retained dataset. Update action receives an object with elementSelector property holding respective nodes collection. In the below example, we set the circle color to '#00ff00' as part of the update action.

update: function(nodes) {
    nodes.circle.setAttr('fill', '#00ff00');
}

Now let's append a new data object {id: 4, label: 'four} with the existing data array.

data.push({id:4, label:'four'});

joinRef.join(data);

On join execution, the update action will be triggered with 3 previously rendered nodes, which will be set to '#00ff00'. And enter action will receive the newly added object, which appears in red in color.

Exit Action:

The exit method defines action on the nodes of the obsolete dataset. Just like the update action, the exit action also receives an object with elementSelector property holding respective nodes collection. In the below example, we remove the circle nodes as part of the exit action.

exit: function(nodes) {
    nodes.circle.remove();
}

now let's remove the 2nd object from the existing data array.

data = [{id:1, label: 'First'}, {id:3, label:'third'}, {id:4, label:'four'}];

On join execution, exit action will be triggered with the nodes associated with the obsolete data. The same will be removed and the remaining nodes will be passed to update action.

Join with multi Elements - circle, text

Join with multi-elements can be performed by passing multi elementSelector string. In the below example, the data join is performed simultaneously between data and circle, text elements.

var joinRef = renderer.join(data,'circle,text',{
                         joinOn:function(d){
                             return d.id;
                         },
                         action:{
                             enter: function(newData){
                                 this.createEls(newData.circle,{
                                          el:'circle',
                                          attr:{
                                                 x:function(d){return d.id*10},
                                                 y:function(d){return d.id*10},
                                                 r:5
                                          },
                                          style:{
                                                 fill:'#ff0000'
                                          }
                                });
                                this.createEls(newData.text,{
                                          el:'text',
                                          attr:{
                                                 x:function(d){return d.id*10},
                                                 y:function(d){return d.id*10 + 20},
                                                 text: function(d) { return d.id }
                                          },
                                          style:{
                                                 fill: 'black',
                                                 text-anchor: 'middle'
                                          }
                                });
                             },
                             exit: function(nodes){
                                    nodes.circle.remove();
                                    nodes.text.remove();
                             },
                             update: function(nodes) {
                                    nodes.circle.setAttr('fill', '#00ff00');
                                    nodes.text.text('fill', function(d){
                                           return d.id;
                                        });
                             }
                     }
                })

Last updated