PDA

View Full Version : EXT 4.2.1 MVC Combobox



whodat
6 Jun 2014, 8:47 AM
I have a Spring MVC backed application using EXTJS 4.2.1. I'm trying to load remote data into a Combobox that is apart of a FormPanel. As I click on the trigger of the Combobox, I see a loading mask but no data is loaded and the request isn't being fired in Firebug.

I'm not sure what is missing, but in Firebug, I see the following error 'TypeError: url is undefined'

I haven't used EXTJS since version 2.3 and I'm trying to learn the new architecture as a POC. Any help will be appreciated.

My code is as follows
Model

Ext.define('TGT.model.State', { extend : 'Ext.data.Model',
fields : [ {
type : 'string',
name : 'label'
}, {
type : 'string',
name : 'value'
} ]
});


Store


Ext.define('TGT.store.StateStore', {
extend: 'Ext.data.JsonStore',
model: 'TGT.model.State',


proxy: {
type: 'ajax',
url: '/common/referencedata/states.json',
reader: {
type: 'json',
root: 'data'
}
},
fields:
[
{name: 'value'},
{name: 'label'}
],
autoLoad: true
});


View


Ext.define('TGT.view.common.StateCombo', {
extend: 'Ext.form.field.ComboBox',
xtype: 'statecombo',
fieldLabel: 'Choose State',
store: 'StateStore',
queryMode: 'remote',
displayField: 'label',
valueField: 'value',
typeAhead: true,
emptyText: 'Select a state...'
});

scottmartin
6 Jun 2014, 9:51 AM
So it is not seeing the URL in your store proxy?

Did you create an instance of the store in your controller or view?

stores: ['StateStore']

Do you see the json response in your network tab?

whodat
6 Jun 2014, 11:50 AM
Hi Scott, thanks for replying. That did the trick. I needed to instantiate a store in my combo's configuration.

In your answer, you mentioned if I created a store in my controller. Is there any example of how that is done and its wired up to the combo or widget?

Updated View for anyone else who gets stuck.


Ext.define('TGT.view.common.StateCombo', {
extend: 'Ext.form.field.ComboBox',
xtype: 'statecombo',
store: new Ext.data.JsonStore({
model: 'TGT.model.State',
proxy: {
type: 'ajax',
url: '/TGT/rest/referencedata/states.json',
reader: {
type: 'json',
root: 'data'
}
},
fields:
[
{name: 'value'},
{name: 'label'}
]
}),
queryMode: 'remote',
displayField: 'label',
valueField: 'value',
emptyText: 'Select a state...'
});

scottmartin
6 Jun 2014, 1:07 PM
In the code you provide in OP, you just need to add:



stores: ['StateStore'] // this will create instance; not the same as requires:[]


Then you just need:


store: 'StateStore', // remember to set autoLoad, or store.load()


This was you do not need to create the instance in the define.

whodat
6 Jun 2014, 3:08 PM
In the code you provide in OP, you just need to add:

I'm assuming this is in the Combobox controller or app.js?


stores: ['StateStore'] // this will create instance; not the same as requires:[]


Then I would add as a property to the combobox, correct?


store: 'StateStore', // remember to set autoLoad, or store.load()



I've tried this and the page containing the combobox doesn't render.

scottmartin
6 Jun 2014, 6:11 PM
>>> I'm assuming this is in the Combobox controller or app.js?

This would be the controller for the view that contains the combo, or app if you want to load at launch

scottmartin
6 Jun 2014, 6:40 PM
Something like this:
6f5

whodat
8 Jun 2014, 3:23 PM
Hi Scott, Thank you for providing a js fiddle example. I've tried to incorporate this in my small app. I also tried this with a grid panel as well and I'm still getting the same error which leads me to believe I am doing something wrong. Can you review this one more time with me? I want to follow the best practices.

I see no request being fired off in Firebug and firebug still reports url is undefined. I know I switched the example but pattern should be the same for either widget.

Controller (gets the store and calls the load method)

Ext.define('TGT.controller.Court', {
extend: 'Ext.app.Controller',
stores: ['Court'],
models: ['Court'],
onLaunch: function() {
// Use the automatically generated getter to get the store
var courtStore = this.getCourtStore();
courtStore.load();
}
});

Model

Ext.define('TGT.model.Court', {
extend: 'Ext.data.Model',
fields:[
{name: 'courtId', type: Ext.data.Types.INT},
{name: 'courtName', type: 'string'},
{name: 'district', type: 'string'},
{name: 'addressLine1', type: 'string'},
{name: 'addressLine2', type: 'string'},
{name: 'city', type: 'string'},
{name: 'state', type: 'string'},
{name: 'zipcode', type: 'string'},
{name: 'county', type: 'string'},
{name: 'country', type: 'string'},
{name: 'createdByUserId', type: 'string'},
{name: 'createDate', type: Ext.data.Types.DATE, dateFormat:'m/d/Y h:i:s A'},
{name: 'updatedUserId', type: 'string'},
{name: 'lastUpdateDate', type: Ext.data.Types.DATE, dateFormat:'m/d/Y h:i:s A'},
]
});

Store

Ext.define('TGT.store.Court', {
extend: 'Ext.data.JsonStore',
model: 'TGT.model.Court',
proxy: {
type: 'ajax',
url: '/rest/courts/allcourts.json',
reader: {
type: 'json',
root: 'courts',
idProperty: 'courtId'
}
},
fields:
[
{name: 'courtId'},
{name: 'courtName'}
]
});

View (references the Court Store as you have in your js fiddle example)

Ext.define('TGT.view.court.CourtSearchResults', {
extend: 'Ext.grid.Panel',
alias: 'widget.courtsearchresults',
store: 'Court',
columns: [
{
xtype:'actioncolumn',
width:50,
items: [{
icon: '/TGT/icons/image_edit.png',
tooltip: 'Edit',
handler: function(grid, rowIndex, colIndex) {

Ext.Msg.alert('Edit Icon', 'Edit clicked.');
}
}]
},
{
xtype:'actioncolumn',
width:50,
items: [{
icon: '/TGT/icons/image_delete.png',
tooltip: 'Edit',
handler: function(grid, rowIndex, colIndex) {

Ext.Msg.alert('Delete Icon', 'Delete clicked.');
}
}]
},
{
xtype: 'gridcolumn',
dataIndex: 'courtName',
text: 'Court Name',
flex: 1
}, {
xtype: 'gridcolumn',
dataIndex: 'district',
text: 'District',
flex: 1
}, {
xtype: 'gridcolumn',
dataIndex: 'addressLine1',
text: 'Address',
flex: 1
}, {
xtype: 'gridcolumn',
dataIndex: 'addressLine2',
text: 'Address Line 2',
flex: 1
}, {
xtype: 'gridcolumn',
dataIndex: 'city',
text: 'City',
flex: 1
}, {
xtype: 'gridcolumn',
dataIndex: 'state',
text: 'State',
flex: 1
}, {
xtype: 'gridcolumn',
dataIndex: 'zipcode',
text: 'Zipcode',
flex: 1
}, {
xtype: 'gridcolumn',
dataIndex: 'county',
text: 'County',
flex: 1
}, {
xtype: 'gridcolumn',
dataIndex: 'country',
text: 'Country',
flex: 1
}, {
xtype: 'gridcolumn',
dataIndex: 'createdByUserId',
text: 'Created By',
flex: 1
}, {
xtype: 'gridcolumn',
dataIndex: 'createDate',
text: 'Created Date',
flex: 1
}, {
xtype: 'gridcolumn',
dataIndex: 'updatedUserId',
text: 'Last Updated By',
flex: 1
}, {
xtype: 'gridcolumn',
dataIndex: 'updatedUserId',
text: 'Last Update Date',
flex: 1
}
]
});

app.js

Ext.application({
name: 'TGT',
controllers: ['Court'],
views: ['court.CourtSearch', 'court.CourtSearchResults'],
models: ['Client', 'State', 'Court'],
stores: ['Clients', 'States', 'Court'],
launch: function(){

},
autoCreateViewport: true
});