# Data Join-Action

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.

{% embed url="<https://codepen.io/nswamy14/pen/LYVeEVz>" %}

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 (**&#x6A;oin 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.

&#x20;**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.

![](https://1744600414-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Lz6CmxFRSBqCTeXXdoA%2F-M22ZtZIdNdLNMCiFNnW%2F-M11ZJnpLz9FWCEk5RRl%2Fjoin1.png?alt=media\&token=d72486be-7c41-4b7b-a960-5c68b739fb5f)

```

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.&#x20;

```
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.

![](https://1744600414-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Lz6CmxFRSBqCTeXXdoA%2F-M22ZtZIdNdLNMCiFNnW%2F-M11hy54yYjdgl_s-NvE%2Fjoin3.png?alt=media\&token=8467b581-854f-4891-bf8e-69738ba5e4d9)

### 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.

![](https://1744600414-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Lz6CmxFRSBqCTeXXdoA%2F-M22ZtZIdNdLNMCiFNnW%2F-M11kSp3t8WREG0KFOQS%2Fjoin4.png?alt=media\&token=a02d2901-f03d-4dc7-9c0f-475f9cbd1e56)

### 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;
                                        });
                             }
                     }
                })
```

![](https://1744600414-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-Lz6CmxFRSBqCTeXXdoA%2F-M22ZtZIdNdLNMCiFNnW%2F-M22aw47-iIYVm0iCuxP%2Fjoin4.png?alt=media\&token=5482bb93-c107-44fe-ae7c-a02722caa33b)
