1. #1
    Sencha User
    Join Date
    Aug 2012
    Location
    UK
    Posts
    13
    Vote Rating
    1
    adambuckley is on a distinguished road

      0  

    Default Answered: Best Practice to Pre-Populate Form from Store in Ext JS 4 MVC

    Answered: Best Practice to Pre-Populate Form from Store in Ext JS 4 MVC


    Hi Folks,

    I've spent 3 days trying to produce a form which is pre-populated with data from a Store. I'm using Ext JS 4.1.1 MVC. I've read a whole heap of tutorials, forums posts, eBooks as well as the API.

    The following is what I've come up with. It's working correctly at present, but please can some Ext experts tell me if this is the best way of doing things.

    Specifically - is my use of afterRender appropriate? Is there any way of setting the value of each form field instead?

    Thanks in advance, Adam.


    app.js
    Code:
    Ext.application({
        name : 'TestApp',
        controllers : [ 'TestController' ],
    
    
        launch : function()
        {
            appGlobal = this;
            
            Ext.create('Ext.container.Viewport',
            {
                layout : 'border',
                padding : 10,
    
    
                items : [
                {
                    xtype : 'testView'
                } ]
            });
        }
    });

    TestController.js
    Code:
    Ext.define('TestApp.controller.TestController',
    {
        extend : 'Ext.app.Controller',
        views : [ 'TestView' ],
        stores : [ 'TestStore' ],
        models : [ 'TestModel' ]
    });

    TestModel.js
    Code:
    Ext.define('TestApp.model.TestModel',
    {
        extend : 'Ext.data.Model',
        fields : [ 'id', 'username', 'firstName', 'surname', 'email' ]
    });

    TestStore.js (will be populated from the server eventually)
    Code:
    Ext.define('TestApp.store.TestStore',
    {
        extend : 'Ext.data.Store',
        model : 'TestApp.model.TestModel',
    
    
        data : [
        {
            id : '123',
            username : 'testuser',
            firstName : 'Test',
            surname : 'User',
            email : 'testuser@conexa.com'
        } ]
    });

    TestView.js
    Code:
    Ext.define('TestApp.view.TestView',
    {
        extend : 'Ext.form.Panel',
        alias : 'widget.testView',
        title : 'Test Form',
        bodyPadding : 10,
    
    
        items : [
        {
            name : 'id',
            xtype : 'displayfield',
            fieldLabel : 'ID'
        },
    
    
        {
            name : 'firstName',
            xtype : 'textfield',
            fieldLabel : 'First Name',
            allowBlank : false
        },
    
    
        {
            name : 'surname',
            xtype : 'textfield',
            fieldLabel : 'Surname',
            allowBlank : false
        },
    
    
        {
            name : 'email',
            xtype : 'textfield',
            fieldLabel : 'Email Address',
            allowBlank : false,
            vtype : 'email'
        } ],
    
    
        afterRender : function()
        {
            this.superclass.afterRender.apply(this);
            var controller = appGlobal.getController('TestController');
            var store = controller.getTestStoreStore();
            var record = store.first();
            this.getForm().loadRecord(record);
        }
    });

  2. With MVC, it's better to move your code to controller instead of leaving it at views:
    - Controller
    Code:
    Ext.define('TestApp.controller.TestController', {
        extend : 'Ext.app.Controller',
        views : [ 'TestView' ],
        stores : [ 'TestStore' ],
        models : [ 'TestModel' ],
        init: function(){
            this.control({
                'testView': {
                    afterrender: function(view){
                        var store = this.getTestStoreStore();
                        var record = store.first();
                        view.getForm().loadRecord(record);
                    }
                }
            });
        }
    });
    - View
    Code:
    Ext.define('TestApp.view.TestView',
    {
        extend : 'Ext.form.Panel',
        alias : 'widget.testView',
        title : 'Test Form',
        bodyPadding : 10,
    
        items : [
        {
            name : 'id',
            xtype : 'displayfield',
            fieldLabel : 'ID'
        },
        {
            name : 'firstName',
            xtype : 'textfield',
            fieldLabel : 'First Name',
            allowBlank : false
        },
        {
            name : 'surname',
            xtype : 'textfield',
            fieldLabel : 'Surname',
            allowBlank : false
        },
        {
            name : 'email',
            xtype : 'textfield',
            fieldLabel : 'Email Address',
            allowBlank : false,
            vtype : 'email'
        } ],
    //    afterRender : function()
    //    {
    //        this.superclass.afterRender.apply(this);
    //        var controller = appGlobal.getController('TestController');
    //        var store = controller.getTestStoreStore();
    //        var record = store.first();
    //        this.getForm().loadRecord(record);
    //    }
    });

  3. #2
    Sencha - Community Support Team
    Join Date
    Jan 2012
    Posts
    1,376
    Answers
    346
    Vote Rating
    113
    vietits is a name known to all vietits is a name known to all vietits is a name known to all vietits is a name known to all vietits is a name known to all vietits is a name known to all

      1  

    Default


    With MVC, it's better to move your code to controller instead of leaving it at views:
    - Controller
    Code:
    Ext.define('TestApp.controller.TestController', {
        extend : 'Ext.app.Controller',
        views : [ 'TestView' ],
        stores : [ 'TestStore' ],
        models : [ 'TestModel' ],
        init: function(){
            this.control({
                'testView': {
                    afterrender: function(view){
                        var store = this.getTestStoreStore();
                        var record = store.first();
                        view.getForm().loadRecord(record);
                    }
                }
            });
        }
    });
    - View
    Code:
    Ext.define('TestApp.view.TestView',
    {
        extend : 'Ext.form.Panel',
        alias : 'widget.testView',
        title : 'Test Form',
        bodyPadding : 10,
    
        items : [
        {
            name : 'id',
            xtype : 'displayfield',
            fieldLabel : 'ID'
        },
        {
            name : 'firstName',
            xtype : 'textfield',
            fieldLabel : 'First Name',
            allowBlank : false
        },
        {
            name : 'surname',
            xtype : 'textfield',
            fieldLabel : 'Surname',
            allowBlank : false
        },
        {
            name : 'email',
            xtype : 'textfield',
            fieldLabel : 'Email Address',
            allowBlank : false,
            vtype : 'email'
        } ],
    //    afterRender : function()
    //    {
    //        this.superclass.afterRender.apply(this);
    //        var controller = appGlobal.getController('TestController');
    //        var store = controller.getTestStoreStore();
    //        var record = store.first();
    //        this.getForm().loadRecord(record);
    //    }
    });

  4. #3
    Sencha User
    Join Date
    Aug 2012
    Location
    UK
    Posts
    13
    Vote Rating
    1
    adambuckley is on a distinguished road

      0  

    Default Thanks Vietits

    Thanks Vietits


    I have now wired my store up to a server as follows.

    But the solution shown above is no longer working, because at the time the afterrender is fired, the store has not yet loaded.

    How can I wait for the store to load?

    Thanks again for your help... Adam.

    Code:
    Ext.define('ProcExt.store.UserProfile',
    {
    	extend : 'Ext.data.Store',
    	model : 'ProcExt.model.UserProfile',
    	autoLoad : true,
    
    
    	proxy :
    	{
    		type : 'rest',
    		url : '/ProcurementServer/profile.json',
    
    
    		reader :
    		{
    			type : 'json',
    			root : 'docs',
    			successProperty : 'success'
    		}
    	}
    });

  5. #4
    Sencha User
    Join Date
    Aug 2012
    Location
    UK
    Posts
    13
    Vote Rating
    1
    adambuckley is on a distinguished road

      0  

    Default I Think This is How It's Done

    I Think This is How It's Done


    This is the controller code. The view is populated in the store.load callback - so we know the store has definitely finished loading.

    Code:
    Ext.define('ProcExt.controller.UserProfile',{
        extend : 'Ext.app.Controller',
        views : [ 'TestView' ],
        stores : [ 'TestStore' ],
        models : [ 'TestModel' ],
    
    
        init : function()
        {
            this.control(
            {
                'testView' :
                {
                    afterrender : function(view)
                    {
                        var store = this.getTestStoreStore();
    
    
                        store.load(function(records, operation, success)
                        {
                            if(success)
                            {
                                var record = store.first();
                                view.getForm().loadRecord(record);
                            }
                            else
                            {
                                // TODO: Complain...
                            }
                        });
                    }
                }
            });
        }
    });

  6. #5
    Sencha User
    Join Date
    Aug 2012
    Location
    UK
    Posts
    13
    Vote Rating
    1
    adambuckley is on a distinguished road

      0  

    Default An Even Better Way

    An Even Better Way


    I think this is an even better way - set the store autoLoad to true, and write a callback which populates the form when the store has finished loading.

    TestController.js
    Code:
    Ext.define('TestApp.controller.TestController',{
        extend : 'Ext.app.Controller',
        views : [ 'TestView' ],
        stores : [ 'TestStore' ],
        models : [ 'TestModel' ],
    
    
        init : function()
        {
            this.getTestStoreStore().addListener('load', function(store, records, success)
            {
                var record = records[0];
                var form = Ext.ComponentManager.get('testView');
                form.getForm().loadRecord(record);
            }, this);
        }
    });

    TestView.js (needs an ID so can be retrieved via Ext.ComponentManager)
    Code:
    Ext.define('TestApp.view.TestView',
    {
        extend : 'Ext.form.Panel',
        alias : 'widget.testView',
        id : 'testView',
        title : 'Test Form',
        ...

    TestStore.js

    Code:
    Ext.define('TestApp.store.TestStore',{
        extend : 'Ext.data.Store',
        model : 'TestApp.model.TestModel',
        autoLoad : true,
    
    
        proxy :
        {
            type : 'ajax',
            url : 'profile.json'
        }
    });
    profile.json (is placed in the same folder as app.js)
    Code:
    {    id : 123,
        username : "user",
        firstName : "Test",
        surname : "User",
        email : "testuser@company.com"
    }

Thread Participants: 1

Tags for this Thread