Ext JS ViewModel:

In the previous section, you learned about Model. Model plays important role in MVC architecture. Ext JS supports MVVM (Model-View-ViewModel) architecture since Ext JS 5 and ViewModel is an important part of MVVM architecture.

ViewModel is a class that manages data for a specific UI component. You can think it as a container of a record for the specific view. It supports two way data binding with UI component so as soon as user changes data in the view, it has a latest copy of it. Unlike model it cannot include proxy so it cannot directly fetch data from the remote server.

Let's create a simple ViewModel with dummy data and bind it to a component. Consider the following example.

Ext.define('MyApp.view.TestViewModel', {
            extend: 'Ext.app.ViewModel',

            alias: 'viewmodel.test',

            data: {
                id: 1,
                name: 'Steve'
            }
        });

        Ext.create('Ext.Component', {

            viewModel:{
                type:'test'
            },

            bind:{
                html:'{id} - {name}'
            },

            renderTo:Ext.getBody()
        });

Try it on Sencha Fiddle.

In the above example, we have created simple ViewModel class called MyApp.view.TestViewModel and extended Ext.app.ViewModel. The alias config is used to give it a short name so that we can refere it with this short name in the UI. The data config is used to provide sample data object. Here, we have provided simple object with id and name properties. The viewmodel class is referenced in a component using viewModel config with the type of viewmodel. Use bind config to bind the specific UI config value with ViewModel's data. In the above example, component's html property bound with the "test" viewmodel data object's id and name property. Use curly brackets to bind a particular property such as '{id}' or '{name}'. So now, the above component will display "1 - Steve".

Now, let's create a simple ViewModel in Ext JS MVVM architecture.

A ViewModel class should be created in a separate JS file under the view folder. For example, ViewModel for Student should be created under app -> view -> student folder in Ext JS MVVM architecture as shown below.

The custom ViewModel class should inherit from Ext.app.ViewModel class.

The following is the sample StudentViewModel class.

Ext.define('MyExtJSApp.StudentViewModel', {
    extend: 'Ext.app.ViewModel',
    alias:'viewmodel.studentviewmodel',
    
    data: {
        firstName: 'James',
        lastName:'Bond'
    },

    formulas: {
                fullName: function(get){
                    return get('firstName') + ' ' + get('lastName');
                }
            }
});

In the above example, we have created a StudentViewModel class which extends Ext.app.ViewModel class. The alias config assigns a name, so that we can refer to it using alias instead of full class name. The data config is used to assign arbitrary data as an object. We have specified two properties, firstName and lastName.

ViewModel can be associated with one or more UI component. We can use bind config property for data binding between ViewModel and component.

The following form component binds firstName and lastName property of the above StudentViewModel with textfields.

Ext.application({
    name: 'SchoolApp',
    requires: ['SchoolApp.StudentViewModel'],

    launch: function() {
        Ext.create('Ext.container.Viewport', {

            items: [{
                xtype: 'form',
                layout:'form',
                bodyPadding: '5',
                buttonAlign: 'center',

                viewModel: {
                    type: 'StudentViewModel'
                },
                
                items: [{
                    xtype: 'textfield',
                    fieldLabel: 'First Name',
                    bind: {
                        value: '{firstName}'
                    }
                }, {
                    xtype: 'textfield',
                    fieldLabel: 'Last Name',
                    bind: {
                        value: '{lastName}'
                    }
                }, {
                    xtype: 'displayfield',
                    fieldLabel: 'Full Name',
                    bind: {
                        value: '{fullName}'
                    }
                }],
                buttons: [{
                    text: 'Save'
                }, {
                    text: 'Reset'
                }]

            }]

        })
    }
});

Try it on https://fiddle.sencha.com/#fiddle/rp6

Links:

ViewModel includes links config that gives a name to a specific record.

For example, the following links config is used to give a name to a Student record whose id is 5.

Ext.define('SchoolApp.view.student.StudentViewModel', {
    extend: 'Ext.app.ViewModel',
    alias:'viewmodel.StudentViewModel',
    
    formulas: {
        fullName: function(get){
            return get('theStudent.firstName') + ' ' + get('theStudent.lastName');
        }
    },
    links: {
        theStudent: {
            type: 'Student',
            id:5
        }
    }
});

ViewModel loads the record from the configured source- Student model class in this case. theStudent uses Student model class to get the record from the remote server.


Live Example

Stores:

ViewModel includes stores config which defines new store or chained store.

The following example demonstrates defining store in the ViewModel.

Ext.define('SchoolApp.view.student.StudentViewModel', {
    extend: 'Ext.app.ViewModel',
    alias:'viewmodel.StudentViewModel',
    formulas: {
        fullName: function(get){
            return get('firstName') + ' ' + get('lastName');
        }
    },
    stores: {
        students: {
            model: 'Student',
            autoLoad: true,
            sorters: [{
                property: 'firstName',
                direction:'DESC'
            }]
        }
    }

});

In the above example, "students" store can be used to bind to a grid component.

Live Example