Skip to content
Modus-Logo-Long-BlackCreated with Sketch.
  • Services
  • About
  • Blog
  • Partners
  • Work
  • Insights
  • Careers
  • Contact
Modus-Logo-Long-BlackCreated with Sketch.
  • Services
  • About
  • Blog
  • Partners
  • Work
  • Insights
  • Careers
  • Contact
June 11, 2012

Expert Ext JS: Model Integration in Forms

Application Development

The Expert Ext JS series details tips and tricks for making the most out of Ext JS. All custom components mentioned are included in Modus Create’s Sencha Plugin Pack available on GitHub.

In Ext JS 4, the data package received a lot of attention and the improvements made were, for the most part, quite impressive. However, the interplay between models and forms remains lackluster. Many folks building a full Ext JS app are not likely to use normal form submission, so getting forms to play nice with models can have significant benefits. With models truly bound to forms, performing normal create, read and update operations can easily take advantage of Proxies, Readers and Writers through Model’s clean API. As it turns out, it’s as easy as this:

Ext.define('MC.form.Panel', {
    extend: 'Ext.form.Panel',

    /**
     * Can be a reference to a model instance or a model class name.
     */
    model: null,
    /**
     * Set to the id of the model instance and the model will be loaded for you.
     * Only applicable if model provided is a model class name (string).
     */
    modelId: null,

    initComponent: function() {

        this.callParent();

        this.getForm().trackResetOnLoad = true; //Workaround

        if (Ext.isString(this.model)) {

            //Load a model to be updated
            if (this.modelId) {

                Ext.ClassManager.get(this.model).load(this.modelId, {
                    failure: this.onModelLoadFailure,
                    success: this.onModelLoadSuccess,
                    scope: this
                });

            //Load an empty record to be inserted
            } else {
                this.bindModel(Ext.create(this.model, {}));
            }

        } else {

            //Bind the provided model to be updated
            this.bindModel(this.model);

        }

        this.addEvents('loadsuccess', 'loadfailure', 'savesuccess', 'savefailure');
    },

    bindModel: function(model) {
        this.model = model;
        this.loadRecord(model);
    },

    commit: function(callback, scope) {
        if (this.form.isDirty()) {
            this.form.updateRecord(this.model);

            this.model.save({
                callback: function(records, operation) {
                    if (operation.wasSuccessful()) {
                        this.fireEvent('savesuccess', this, records, operation);
                    } else {
                        this.fireEvent('savefailure', this, records, operation);
                    }
                    if (callback) {
                        callback.call(scope || this, this, operation.wasSuccessful(), this.model);
                    }
                },
                scope: this
            });
        }
    },

    onModelLoadSuccess: function(record, operation) {
        this.bindModel(record);
        this.fireEvent('loadsuccess', this, record, operation);
    },

    onModelLoadFailure: function(record, operation) {
        this.fireEvent('loadfailure', this, record, operation);
    }

});

As you can see FormPanel and BasicForm provide most of the needed logic with loadRecord() and updateRecord() and it’s just a little extra legwork to simplify model integration.

One issue I identified was that trackResetOnLoad was not propagated down to BasicForm as promised in the docs, which is why that’s noted in my comment above.

Now let’s take a look at how we can use this with a concrete example:

Ext.define('User', {
    extend: 'Ext.data.Model',
    fields: ['id', 'name', 'email', 'dob'],
    proxy: {
        type: 'rest',
        api: {
            create: '/user/create',
            read: '/user/read',
            update: '/user/update'
        }
    }
});

Ext.define('UserForm', {
    extend: 'MC.form.Panel',

    model: 'User',

    initComponent: function() {
        this.items = [
            {
                xtype: 'textfield',
                fieldLabel: 'Email Address',
                name: 'email'
            },
            {
                xtype: 'textfield',         
                fieldLabel: 'Name',
                name: 'name'
            },
            {
                xtype: 'datefield',
                fieldLabel: 'Date of Birth',
                name: 'dob'
            },
            {
                xtype: 'button',
                text: 'Submit',
                handler: this.commit,
                scope: this
            }
        ];
        this.callParent();
    }
});


//Create a new user
var newUserForm = Ext.create('UserForm'); //will create a phantom model

//Modify an existing user for which you only have the id
var newUserForm = Ext.create('UserForm', { modelId: 1234 });

//Modify an existing user for which you have an existing model
var user = Ext.create('User', { id: 1234, name: 'Aaron Smith' });
var existingUserForm = Ext.create('UserForm', { model: user });

Next week, we’ll discuss using this Form Panel with Associations!

Posted in Application Development
Share this

Jay Garcia

Jay Garcia is co-founder and managing director at Modus Create. He is a U.S. Air Force veteran with 20 plus years of technology and consulting experience in leading RIA development for companies around the world. He is co-organizer of the NoVa.JS and NYC.JS meetups, and is actively involved in the software communities that provide business frameworks and technologies, which enable rich mobile and desktop web experiences.
Follow

Related Posts

  • ExtJS
    Expert Ext JS: Associations in Forms

    Associations were a major addition to the data package in Ext JS 4 and, to…

  • Ext JS to React: Selection Model
    Ext JS to React: Selection Model

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

Subscribe to the Modus Newsletter

Receive the latest insights from our team each month.

modus create logo_white
  • Services
  • About
  • Partners
  • Work
  • Insights
  • Careers

© 2023 Modus. All Rights Reserved.

Privacy Policy | Accessibility Statement | Sitemap

Scroll To Top