Ext.js 4 window with form cals servlet which returns JSON but unable to populate gridpanel

Go To StackoverFlow.com

1

I am using Ext.js 4 with MVC. I have a window which pops up, and asks the user for some criteria. That window calls a servlet, which returns the data as JSON, and should then populate a grid. I can see thru Firefly that the JSON object IS be returned. However, the grid is not being populated. The reason is that a subsequent call to the servlet is beign made. This is because I have the URL specified in two places. I know this is wrong, but if either one is omitted I get error messages.

This is app/controller/PSLocators.js

Ext.define('MyApp.controller.PSLocators', {
    extend: 'Ext.app.Controller',
    stores: [ 'PSLocators' ],
    models: [ 'PSLocator' ],
    views : [ 'pslocator.List' ]
});

This is app/model/PSLocator.js

Ext.define('MyApp.model.PSLocator', 
{
    extend: 'Ext.data.Model',
    fields: 
    [
        'id', 
        'name',
        'address',
        'city',
        'state',
        'zip',
    ]
});

This is app/store/PSLocators.js. This has the first of the urls. This is the one that returns no data. I don't think I should have the proxy{} here, but if I delete the proxy { } I get the error message

uncaught exception: [Exception... "'You are using a ServerProxy but have not supplied it with a url.' when calling method: [nsIDOMEventListener::handleEvent]" 
nsresult: "0x8057001c (NS_ERROR_XPC_JS_THREW_JS_OBJECT)" 
location: "JS frame :: chrome://firebug/content/net/spy.js :: callPageHandler :: line 812" data: no]"


Ext.define('MyApp.store.PSLocators', {
    extend: 'Ext.data.Store',
    model: 'MyApp.model.PSLocator',
    autoLoad: false,    // see also activate() in grid panel
    sortOnLoad: false,  // sorted by SAS
    proxy: 
    {
        type: 'ajax',
        url: MyGlobalData.contextPath + '/PSLocator',
        reader: 
        {
            type: 'json',
            root: 'data',  // the name of the array within the JSON dataset
            totalProperty: 'results',
            successProperty: 'success'
        }
    }
});

This is the app/view/pslocator/List.js. This has the second of the urls. This url is returning the data correctly as JSON. If I delete the url I get the error message "uncaught exception: No URL specified"

Ext.define('MyApp.view.pslocator.List' ,{
    extend: 'Ext.grid.Panel',
    alias : 'widget.pslocatorlist',
    store : 'PSLocators',
    title : 'Store Locator',
    id    : 'pslocator.List',

    autoScroll: true,
    height: 400,
    columnLines: true,

    initComponent: function()
    {
        this.columns = [
            {header: 'ID'          , dataIndex: 'id'        , flex: .05 , align: 'center' },
            {header: 'Name'        , dataIndex: 'name'      , flex: .20 , align: 'left'   },
            {header: 'Address'     , dataIndex: 'address'   , flex: .20 , align: 'left'   },
            {header: 'City'        , dataIndex: 'city'      , flex: .10 , align: 'left'   },
            {header: 'State'       , dataIndex: 'state'     , flex: .05 , align: 'center' },
            {header: 'Zip'         , dataIndex: 'zip'       , flex: .05 , align: 'center' }
        ];

        this.callParent(arguments);
    },

    listeners:
    {
        activate: function()
        {
            this.un('activate', arguments.callee);
            var win = new Ext.Window(
            {
                id: 'id-pslocator-window',
                title: 'Show locations near which store?',
                items: [
                {
                    xtype      : 'form',
                    id         : 'id-pslocator-form',
                    bodyPadding: 5,
                    width      : 500,
                    height     : 125,
                    autoScroll : false,

                    // The form will submit an AJAX request to this URL when submitted
                    url: MyGlobalData.contextPath + '/PSLocator',

                    layout: 'auto',

                    defaults: 
                    {
                        anchor: '100%'
                    },

                    items: [
                    {
                        xtype       : 'textfield',
                        fieldLabel  : 'Store number',
                        name        : 'pStoreNumber',
                        labelWidth  : 200,
                        width       : 300,  // includes labelWidth
                        allowBlank  : false,
                        regex       : /^([0-9]+)([ ]*)$/,  
                        regexText   : 'Must be a single unsigned integer.',
                    }
                ],

                // Reset and Submit buttons
                buttons: [
                    {
                        text: 'Reset',
                        handler: function() 
                        {
                            this.up('form').getForm().reset();
                        }
                    },
                    {
                        text: 'Submit',
                        formBind: true, //only enabled once the form is valid
                        disabled: true,
                        handler: function() 
                        {
                            var form = this.up('form').getForm();
                            if (form.isValid()) 
                            {
                                form.submit(
                                {
                                    success: function(form, action) 
                                    {
                                        console.log('In success function');
                                        var myGrid = Ext.getCmp('id-pslocator-panel');
                                        console.log('myGrid = ' + myGrid);
                                        var myStore = myGrid.getStore();
                                        console.log('myStore = ' + myStore);
                                        myStore.load();  /* requires store be defined as above */
                                        myGrid.getView().refresh();

                                        var myPopup = Ext.getCmp('id-pslocator-window');
                                        myPopup.destroy();

                                    }  // end success function
                                });  // end form submit
                            }  // end if is valid
                        }  // end handler
                    }   //  end submit
                ]   // end buttons
                }]  // end items
            }); // end win

            win.show();
            // this.store.load();
        }
    }
});  // Ext.define

Can someone please help, or point me to a working example (reminder: I am attempting the use the MVC architecture.)

2012-04-04 17:31
by Bill Qualls


0

You should store the proxy configuration in the model rather than the store in ExtJS4. Also It looks like you are just wanting to limit the search on your stores to a particular store number. You shouldn't need to submit a POST request via the form to do this. You should add a filter to your store so the server can return the correct data.

DISCLAIMER: I've not tested this code out, but it should be enough to get you going.

app/model/PSLocator.js

Ext.define('MyApp.model.PSLocator', 
{
    extend: 'Ext.data.Model',
    fields: 
    [
        'id', 
        'name',
        'address',
        'city',
        'state',
        'zip',
    ],
    proxy: 
    {
        type: 'ajax',
        url: MyGlobalData.contextPath + '/PSLocator',
        reader: 
        {
            type: 'json',
            root: 'data',  // the name of the array within the JSON dataset
            totalProperty: 'results',
            successProperty: 'success'
        }
    }
});

app/store/PSLocators.js

Ext.define('MyApp.store.PSLocators', {
    extend: 'Ext.data.Store',
    model: 'MyApp.model.PSLocator',
    autoLoad: false,    // see also activate() in grid panel
    sortOnLoad: false,  // sorted by SAS,
    remoteFilter: true  // Needed so filter changes will go to the server
});

app/view/pslocator/List.js

Ext.define('MyApp.view.pslocator.List' ,{
    extend: 'Ext.grid.Panel',
    alias : 'widget.pslocatorlist',
    store : 'PSLocators',
    title : 'Store Locator',
    id    : 'pslocator.List',

    autoScroll: true,
    height: 400,
    columnLines: true,

    initComponent: function()
    {
        this.columns = [
            {header: 'ID'          , dataIndex: 'id'        , flex: .05 , align: 'center' },
            {header: 'Name'        , dataIndex: 'name'      , flex: .20 , align: 'left'   },
            {header: 'Address'     , dataIndex: 'address'   , flex: .20 , align: 'left'   },
            {header: 'City'        , dataIndex: 'city'      , flex: .10 , align: 'left'   },
            {header: 'State'       , dataIndex: 'state'     , flex: .05 , align: 'center' },
            {header: 'Zip'         , dataIndex: 'zip'       , flex: .05 , align: 'center' }
        ];

        this.callParent(arguments);
    }
});  // Ext.define

app/view/pslocator/Window.js

Ext.define('MyApp.view.pslocator.Window', {
    extend: 'Ext.Window',
    alias: 'widget.storeselector',
    id: 'id-pslocator-window',
    title: 'Show locations near which store?',
    items: [
    {
        xtype      : 'form',
        id         : 'id-pslocator-form',
        bodyPadding: 5,
        width      : 500,
        height     : 125,
        autoScroll : false,

        // The form will submit an AJAX request to this URL when submitted
        url: MyGlobalData.contextPath + '/PSLocator',

        layout: 'auto',

        defaults: 
        {
            anchor: '100%'
        },

        items: [
        {
            xtype       : 'textfield',
            fieldLabel  : 'Store number',
            name        : 'pStoreNumber',
            labelWidth  : 200,
            width       : 300,  // includes labelWidth
            allowBlank  : false,
            regex       : /^([0-9]+)([ ]*)$/,  
            regexText   : 'Must be a single unsigned integer.',
        }
    ],

    // Reset and Submit buttons
    buttons: [
        {
            text: 'Reset',
            handler: function() 
            {
                this.up('form').getForm().reset();
            }
        },
        {
            text: 'Submit',
            formBind: true, //only enabled once the form is valid
            disabled: true,
            handler: function() 
            {
                var form = this.up('form').getForm();
                if (form.isValid()) 
                {
                    this.fireEvent('storeselected', form.getValues().pStoreNumber);
                    this.destroy();
                }  // end if is valid
            }  // end handler
        }   //  end submit
    ]   // end buttons
    }]  // end items
});

app/controller/PSLocators.js

Ext.define('MyApp.controller.PSLocators', {
    extend: 'Ext.app.Controller',
    stores: [ 'PSLocators' ],
    models: [ 'PSLocator' ],
    views : [ 'pslocator.List' ],
    init: function() {
        this.control({
            'pslocatorlist': {
                activate: this.showStoreSelector
            },
            'storeselector': {
                storeselected: this.updatePSLocatorStore
            }
        );
    },

    showStoreSelector: function()
    {
        var win = Ext.create('MyApp.view.pslocator.Window');
        win.show();
    },

    updatePSLocatorStore: function(storeId) {
        this.getPSLocationsStore().filter('id', storeId);
        this.getPSLocationsStore().load(); // I can't remember if this step is needed.
    }
});

I think thats about as best I can get it from reading over the code. It should give you an idea of how you can use the MVC technique to your advantage and hopefully get you on the right path.

2012-04-05 09:32
by Jamie Sutherland
Thanks for the effort. I sincerely appreciate it. I am late getting back to this because another "rush" assignment came in. (Isn't that always the case?) I tried making the changes you recommended, but still not working. Probably my own lack of understanding. Nevertheless, I am not comfortable with the filtering recommended here. Unless I am misunderstanding, this solution is relying on the server to return ALL records, and the client to do the filtering. There are a lot of records to be returned - Bill Qualls 2012-04-09 17:40
No there is a config option in there set to send all filtering requests to the server - Jamie Sutherland 2012-04-09 21:13
No worries Bill :)

No there is a config option in there set to send all filtering requests to the server. In the store setup you configure the following.

remoteFilter: true

So that the filters are sent as query variables to your webservice. Like so

/PSLocator?filterName=filterValue

From your original post it looked like you were sending a POST to filter the store location on your form submit. So unless your server side application keeps state? this won't have an effect on your store data. You want to do is update the store filter when the correct storeID and reload the store - Jamie Sutherland 2012-04-09 21:19

Ultimately, my solution was to use extraParams option - Bill Qualls 2012-04-21 00:22
Ads