Skip to content

Modus-Logo-Long-BlackCreated with Sketch.

  • Services
  • Work
  • Blog
  • Resources

    OUR RESOURCES

    Innovation Podcast

    Explore transformative innovation with industry leaders.

    Guides & Playbooks

    Implement leading digital innovation with our strategic guides.

    Practical guide to building an effective AI strategy
  • Who we are

    Our story

    Learn about our values, vision, and commitment to client success.

    Open Source

    Discover how we contribute to and benefit from the global open source ecosystem.

    Careers

    Join our dynamic team and shape the future of digital transformation.

    How we built our unique culture
  • Let's talk
  • EN
  • FR

Ext JS to React: Binding with React

Published on April 3, 2018
Last Updated on April 23, 2021
Application Development

This is part of the Ext JS to React blog series. You can review the code from this article on the Ext JS to React Git repo.

With Ext JS 5, the concept of view models was introduced into the application architecture. The data used by an application’s components could be sourced from data housed in the view model. Conversely, updates in the UI could send data back up to the view model in a bidirectional relationship. Data in React, however, flows in only one direction. Data is supplied to components via props passed in from a parent component or through a binding with an application state manager like Redux.

Note: While not a requirement for React, this article’s code examples assume you’re starting with a starter app generated by create-react-app.

Ext JS Simple Binding Example

Let’s look at a simple example using an HTML form and several fields. With Ext JS you have to define a view model and then configure bindings for the individual fields:

Ext.define('MyApp.view.User', {
    extend : 'Ext.form.Panel',
    xtype  : 'myapp-user',

    controller : {
        xclass : 'MyApp.view.UserController'
    },

    viewModel : {
        xclass : 'MyApp.view.UserModel'
    },

    defaultType : 'textfield',

    items : [
        {
            xtype      : 'displayfield',
            fieldLabel : 'User ID',
            name       : 'id',
            bind       : '{user.id}'
        },
        {
            fieldLabel : 'Name',
            name       : 'name',
            bind       : '{user.name}'
        },
        {
            fieldLabel : 'Email',
            name       : 'email',
            bind       : '{user.email}'
        },
        {
            fieldLabel : 'Phone Number',
            name       : 'phone',
            bind       : '{user.phone}'
        },
        {
            fieldLabel : 'Company',
            name       : 'company',
            bind       : '{user.company}'
        },
        {
            fieldLabel : 'Department',
            name       : 'department',
            bind       : '{user.department}'
        },
        {
            fieldLabel : 'Title',
            name       : 'title',
            bind       : '{user.title}'
        }
    ],

    buttons: [
        {
            text    : 'Submit', 
            handler : 'submit' // in the View Controller
        }
    ]
});

Given this Ext JS form, a common source for the data would be from an ajax call loading a store. The store could additionally be used to populate a grid. The grid’s selection model would be tied to the view model. Meaning that by selecting a row in the grid, the “user” record data would automatically be updated and then displayed in the form.

React Form Class

With React, there is no need for a dedicated view model class to hold the data. If you provide the data to a parent container, it can pass the appropriate data to the child fields. Child fields can then relay any changes to the parent container. The binding in the following React example form uses the properties on the fields:

import React, { Component } from 'react';

class Form extends Component {
  state = {
    user: Object.assign({}, this.props.user)
  };

  componentWillReceiveProps({ user }) {
    this.setState({
      user: Object.assign({}, user)
    });
  }

  render() {
    const { renderField, state, submit } = this;

    return (
      <form>
        {renderField(state, 'name')}
        {renderField(state, 'email', undefined, 'email')}
        {renderField(state, 'phone', 'Phone Number', 'tel')}
        {renderField(state, 'company')}
        {renderField(state, 'department')}
        {renderField(state, 'title')}

        <button onClick={submit}>Submit</button>
      </form>
    );
  }

  renderField = (state, name, label = name, type = 'text') => {
    return (
      <div style={{ marginBottom: '12px' }}>
        <label style={{textTransform: 'capitalize'}}>
          {label}
          <input
            type="text"
            name={name}
            value={state.user[name] || ''}
            onChange={this.handleFieldChange}
            style={{ marginLeft: '12px' }}
          />
        </label>
      </div>
    );
  };

  handleFieldChange = e => {
    const { name, value } = e.target;
    const user = Object.assign({}, this.state.user, { [name]: value });

    this.setState({ user });
  };

  submit = e => {
    e.preventDefault();

    // do submit
  };
}

export default Form;

We can use the form class in our starter app with the following:

import React from 'react';
import Form from './Form';

const App = () => <Form/>;

export default App;
Ext JS to React: Binding with React

React Form Class Explained

This may seem familiar from code you’ve seen in the form article. What’s going on here is the form is taking a user prop (from Form user={user} when instantiated) and setting values from that object onto each child input using the renderField method. The part here that is binding is the value prop on the input field. When data is passed as a prop to the form, changes to the value for each bound form field will result in that field being re-rendered.

As you type in a field, there is an onChange listener that updates the state. This updating will re-trigger a render process so that React can determine whether there was a DOM update that needs to happen. Once the state changes, that value is passed down to the fields to be updated since their input text is derived from the parent form’s state. In this example, we also used the componentWillReceiveProps lifecycle method. This is done so that if the parent’s user prop is ever updated the fields’ values remain in sync.

You can review the sample code on the Git repo.

Communicating Changes To a Parent Component

In this last example, something passed the user data to the form and the form managed its internal state based on any of the child items being changed. What if you don’t want to submit a form? What if instead, you want to notify the something passing in the data that a change was made? For example, say you have a grid and when you click on a row it shows a form to edit that row’s data. As you type you want the grid row to reflect the changes live. Ext JS allows for two-way binding which would support this, but React says data flows one way and that’s down. So there is no way to have React automatically update the parent data from one of the form fields.

In the last example, we used Object.assign to clone the user object so that we didn’t accidentally edit data. Since we nested the data within the user prop, that object is not handled by React. The object that was passed to the Form class is the same that is applied to the state if we didn’t use Object.assign to create a new object. Even though you technically can get two-way binding here, React’s convention only supports one-way, downstream binding. Additionally, React will not re-render if you simply update a property of a nested object.

Calling a Parent Method Example

In order to notify the entity that instantiated the form, it’s common to pass down a function that the form can execute:

import React from 'react';
import Form from './Form';

const App = () => (
  <Form
    onChange={change => {
      console.log('change', change);
    }}
  />
);

export default App;

Now within that onChange function that was passed, we can execute the following within the handleFieldChange method:

handleFieldChange = e => {
  const { onChange } = this.props;
  const { name, value } = e.target;
  const change = { [name]: value };
  const user = Object.assign(this.state.user, change);

  if (onChange) {
    onChange(change);
  }

  this.setState({ user });
};

With this handler in place we only pass what changed. That allows us to patch the full user object we passed to the form and perform any action needed. As a user types in one of the fields, the onChange function is executed. This allows us to handle the change such as updating the grid row data on the fly. In doing so, we’ve created a two-way binding relationship without breaking React conventions! This can be a great way to perform real-time checks such as field validations. For example, an asynchronous check can be done on the server to ensure a username entered is not only valid, but currently available.

You can review the sample code on the Git repo.

Wrap Up

Since Ext JS is more than just a view library like React, it has mechanisms to handle two-way binding. React only wants to use one-way binding exclusively. However, as we’ve explored in the examples above, there are still ways to notify parent components of the changes announced from child items. Fortunately, the feedback loop between components is easy to set up and only needs to be created as the situation dictates leaving your code base as lean as possible! Stay tuned for the coming blogs where we continue to look at how data is managed within your application using the popular state manager, Redux.

Posted in Application Development
Share this

Mitchell Simoens

Mitchell Simoens is a Senior Front End Engineer at Modus Create. Mitchell has spent the last 10 years working with Ext JS including developing core functionality, Sencha Fiddle and (I hope your insurance covers blown minds) supporting the online community with over 40,000 posts on the Sencha Forums. Before working with Ext JS, Mitchell used Perl and PHP but loves spending time with Node JS for today's needs. When not working, you can find Mitchell relaxing with his wife and daughter, or developing his talents as an amateur furniture maker.
Follow

Related Posts

  • Ext JS to React: Form Submission
    Ext JS to React: Form Submission

    This is part of the Ext JS to React blog series. You can review the…

  • React Landing
    Ext JS to React: Migration to Open Source

    Worried about Migrating from Ext JS? Modus has the Answers Idera’s acquisition of Sencha has…

Want more insights to fuel your innovation efforts?

Sign up to receive our monthly newsletter and exclusive content about digital transformation and product development.

What we do

Our services
AI and data
Product development
Design and UX
IT modernization
Platform and MLOps
Developer experience
Security

Our partners
Atlassian
AWS
GitHub
Other partners

Who we are

Our story
Careers
Open source

Our work

Our case studies

Our resources

Blog
Innovation podcast
Guides & playbooks

Connect with us

Get monthly insights on AI adoption

© 2025 Modus Create, LLC

Privacy PolicySitemap
Scroll To Top
  • Services
  • Work
  • Blog
  • Resources
    • Innovation Podcast
    • Guides & Playbooks
  • Who we are
    • Our story
    • Careers
  • Let’s talk
  • EN
  • FR