Categories: JavascriptUI

ReactJS Tutorial – How to Add or Delete Table Row Dynamically



The article represents high-level concepts including component design and event delegation and, demo/code samples in relation with how to add or delete a table row dynamically. For AngularJS enthusiasts, it also presents quick differences and few similarities (so to say) as well. The UI is demonstrated on the following page: http://tuts-javascript.appspot.com/reactjs-add-remove-table-row. Feel free to comment/suggest on any aspects of the article including concepts and code samples.

Following is how the design is laid out:

  • CompanyApp: The app has a top-level component named as CompanyApp. This component is composed of following components:
    • CompanyList: CompanyList component represents a list of companies and has code to render the same.
      • Company: Company component represents the company and has an onClick event for removing the company.
    • NewRow: NewRow component is used to capture the data (company information). It has an onSubmit form event to capture row submit.

From above, one thing that becomes clear is the component-oriented design. In above design, CompanyApp is the composite component that is composed of two other components named as CompanyList and NewRow. In addition, CompanyList is a composite component that is composed of list of Company components.

This is where the power of ReactJS shows up. One could design the UI as components and, then write the code appropriately to achieve the following key objectives:

  1. Render the components: Watch in following code samples how the render API is defined for each component and also, the related HTML like code. For Angular enthusiasts, it may look like custom directives as there are markups on custom components.
  2. Handle the event based on event delegation model. Note how the event is delegated to container/parent component using callback methods.

Overview of CompanyApp

Notice the following concepts in the code below:

  • getInitialState API called to set the initial state to the default list passed to the CompanyApp component
  • handleNewRowSubmit: This API is used to change the state due to addition of a new company. Note the “setState” method being called to set the new state. This ensures that UI gets updated with new data.
  • handleCompanyRemove: This API is used to change the state due to removal of company from existing company list. Again, note the “setState” method invoked which ensures that UI gets updated.

For AngularJS enthusiasts, following points (differences/similarities) can be noted:

  • For updating UI, all that is needed to be done is change the UI state model, companylist in the example below, and invoke “setState” method to update the UI.
  • CompanyList and NewRow gives a feeling of custom directives. 🙂 These are actually React components.
  • I have to admit that I ended up writing more code to achieve the same objective in ReactJS.  Also, UI code is embedded with Component’s definition. Take a look at this demo done with AngularJS.
var CompanyApp = React.createClass({
        getInitialState: function() {
          return {companylist:this.props.companies};
        },
        handleNewRowSubmit: function( newcompany ) {
          this.setState( {companylist: this.state.companylist.concat([newcompany])} );
        },
        handleCompanyRemove: function( company ) {

          var index = -1; 
          var clength = this.state.companylist.length;
        for( var i = 0; i < clength; i++ ) {
         if( this.state.companylist[i].cname === company.cname ) {
          index = i;
          break;
         }
        }
        this.state.companylist.splice( index, 1 ); 
        this.setState( {companylist: this.state.companylist} );
        },
        render: function() {
          var tableStyle = {width: '100%'};
          var leftTdStyle = {width: '50%',padding:'20px',verticalAlign: 'top'};
          var rightTdStyle = {width: '50%',padding:'20px',verticalAlign: 'top'};
          return ( 
            

<table style={tableStyle}>
              

<tr>
                

<td style={leftTdStyle}>
                  <CompanyList clist={this.state.companylist} onCompanyRemove={this.handleCompanyRemove}/>
                </td>


                

<td style={rightTdStyle}>
                  <NewRow onRowSubmit={this.handleNewRowSubmit}/>
                </td>


              </tr>


          </table>


          );
        }
      });

 

CompanyList Class: Displays a list of Companies

Notice the following concepts in the code below:

  • handleRemoveCompany invokes the onCompanyRemove method which invokes the callback method to pass the event upward in the hierarchy.
  • render method which creates the table
  • Company component which is passed the company (later accessed as this.props.company) property to create the row.
var CompanyList = React.createClass({
        handleCompanyRemove: function(company){
          this.props.onCompanyRemove( company );
        },
        render: function() {
          var companies = [];
          var that = this; // TODO: Needs to find out why that = this made it work; Was getting error that onCompanyDelete is not undefined
          this.props.clist.forEach(function(company) {
            companies.push(<Company company={company} onCompanyDelete={that.handleCompanyRemove} /> );
          });
          return ( 
            

<div>
              

<h3>List of Companies</h3>


              

<table className="table table-striped">
                

<thead>

<tr>

<th>Company Name</th>


<th>Employees</th>


<th>Head Office</th>


<th>Action</th>

</tr>

</thead>


                

<tbody>{companies}</tbody>


              </table>


            </div>


            );
        }
      });

 

Company Class

Notice the following concepts in the code below:

  • handleRemoveCompany invokes the onCompanyDelete method which invokes the callback method to pass the event upward in the hierarchy to remove or delete the existing company from the company list. Remember the event delegation model.
var Company = React.createClass({
        handleRemoveCompany: function() {
          this.props.onCompanyDelete( this.props.company );
          return false;
        },
        render: function() {
          return (
            

<tr>
              

<td>{this.props.company.cname}</td>


              

<td>{this.props.company.ecount}</td>


              

<td>{this.props.company.hoffice}</td>


              

<td><input type="button" className="btn btn-primary" value="Remove" onClick={this.handleRemoveCompany}/></td>


            </tr>


            );
        }
      });</pre>
</div>

&nbsp;
<div>
<h3 style="background-color: #81d4fa; padding: 15px;">New Row is Added</h3>

Notice the following concepts in the code below:
<ul>
<li>handleSubmit reads/captures the input and invokes the onRowSubmit method which invokes the <strong>callback method</strong> to pass the event upward in the hierarchy to add a new company (row) in the table. <strong>Remember the event delegation model.</strong></li>
</ul>
<pre lang="xml" escaped="true">var NewRow = React.createClass({
        handleSubmit: function() {
          var cname = this.refs.cname.getDOMNode().value;
          var ecount = this.refs.ecount.getDOMNode().value;
          var hoffice = this.refs.hoffice.getDOMNode().value;
          var newrow = {cname: cname, ecount: ecount, hoffice: hoffice };
          this.props.onRowSubmit( newrow );

          this.refs.cname.getDOMNode().value = '';
          this.refs.ecount.getDOMNode().value = '';
          this.refs.hoffice.getDOMNode().value = '';
          return false;
        },
        render: function() {
          var inputStyle = {padding:'12px'}
          return ( 
            

<div className="well">
              

<h3>Add A Company</h3>


            

<form onSubmit={this.handleSubmit}>
              

<div className="input-group input-group-lg" style={inputStyle}>
                <input type="text" className="form-control col-md-8" placeholder="Company Name" ref="cname"/>
              </div>


              

<div className="input-group input-group-lg" style={inputStyle}>
                <input type="text" className="form-control col-md-8" placeholder="Employee Count" ref="ecount"/>
              </div>


              

<div className="input-group input-group-lg" style={inputStyle}>
                <input type="text" className="form-control col-md-8" placeholder="Headoffice" ref="hoffice"/>
              </div>


              

<div className="input-group input-group-lg" style={inputStyle}>
                <input type="submit" className="btn btn-primary" value="Add Company"/>
              </div>


            </form>


); } });

The code could be found on this Hello ReactJS – github page. Feel free to comment on the design or event delegation model as I am also in the learning phase at this point.

Ajitesh Kumar

I have been recently working in the area of Data analytics including Data Science and Machine Learning / Deep Learning. I am also passionate about different technologies including programming languages such as Java/JEE, Javascript, Python, R, Julia, etc, and technologies such as Blockchain, mobile computing, cloud-native technologies, application security, cloud computing platforms, big data, etc. For latest updates and blogs, follow us on Twitter. I would love to connect with you on Linkedin. Check out my latest book titled as First Principles Thinking: Building winning products using first principles thinking. Check out my other blog, Revive-n-Thrive.com

View Comments

  • I configured like index.html and app.js then I ran like npm run webpack

    Earlier I did simple form table and click on submit button then shows the data in the table.

    Please suggest on this . It would be great for me.

    Thanks in advance.........
    Ravi

    • Please send me the working copy of "ReactJS Tutorial – How to Add or Delete Table Row Dynamically" in reactJs Example.

      Thanks,
      Ravi

    • Sorry, i am struck in edit function in same ur code, pls share me edit function
      Your comment is awaiting moderation.

  • The reason you needed that = this is because within that inner function, "this" no longer refers to the outer component.

Share
Published by
Ajitesh Kumar
Tags: reactjs

Recent Posts

Mean Squared Error vs Cross Entropy Loss Function

Last updated: 28th April, 2024 As a data scientist, understanding the nuances of various cost…

2 days ago

Cross Entropy Loss Explained with Python Examples

Last updated: 28th April, 2024 In this post, you will learn the concepts related to…

2 days ago

Logistic Regression in Machine Learning: Python Example

Last updated: 26th April, 2024 In this blog post, we will discuss the logistic regression…

3 days ago

MSE vs RMSE vs MAE vs MAPE vs R-Squared: When to Use?

Last updated: 22nd April, 2024 As data scientists, we navigate a sea of metrics to…

5 days ago

Gradient Descent in Machine Learning: Python Examples

Last updated: 22nd April, 2024 This post will teach you about the gradient descent algorithm…

1 week ago

Loss Function vs Cost Function vs Objective Function: Examples

Last updated: 19th April, 2024 Among the terminologies used in training machine learning models, the…

2 weeks ago