Results 1 to 5 of 5

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

  1. #1
    Sencha User
    Join Date
    Aug 2012
    Location
    UK
    Posts
    13
    Vote Rating
    1
      0  

    Default 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 User
    Join Date
    Jan 2012
    Posts
    1,376
    Answers
    347
    Vote Rating
    116
      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
      0  

    Default 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
      0  

    Default 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
      0  

    Default 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"
    }

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •