PDA

View Full Version : this.store has no properties combobox



luv2hike
21 Feb 2008, 8:59 PM
I am stuck. I keep getting this error message when I try to open a form panel from a grid. The form is defined in an included js file and contains a combobox whose store is the same store as a grid in another tab and is defined in the main file. The store variable is global. I have tried every combination I can think of and have literally spent the day chasing this but with no success. It used to work but only quit when I moved the form into a card layout panel.

I can get around this by redefining the same store with a different variable name in the script file in which the combo box is defined. However, this then causes the combo box to only show the currently selected value as the ID number instead of the text for it. There are no other items in the list when the drop arrow is clicked.

Please help. I'm at my wit's end with this. Currently my code has gotten so hacked up from trial and error and trying so many different ways to get it to work that it won't be too helpful. If I get a version cleaned up and back to "pristine" state, I'll add it.

Condor
21 Feb 2008, 11:10 PM
You probably didn't recreate the store exactly the same. Do the field names of the record match the displayField and the valueField of the combobox?

ps. You can use the store for both comboboxes if the data in the store never changes (this also means that you have to autoLoad the store and use the comboboxes with mode:'local' and triggerAction:'all').

luv2hike
22 Feb 2008, 6:45 AM
Thanks for the response. I have code now I can post. There is only 1 combo box. The component it shares a store with is an EditorGridPanel. Which leads also to the issue you may have touch upon of will the combo box dropdown list update when the user edits the grid (which commits changes to the store)?

I think what may be going on is I have a basic misunderstanding of the sequence of load events when using ExtJS, as well as a confusion on a Store's relationship to its views. Any guidance to either or both of these issues would be great!

Specifically, if the following code fragment is inside the main file, index.jsp:



<html>
<head>
<link rel="stylesheet" type="text/css" href="resources/css/ext-all.css"/>
<link rel="stylesheet" type="text/css" href="resources/css/xtheme-indigo.css"/>

<style type="text/css">
.add {
background-image:url(add.gif) !important;
}
.remove {
background-image:url(delete.gif) !important;
}
.save {
background-image:url(save.gif) !important;
}
</style>
</head>
<body>
<!-- LIBS -->
<script type="text/javascript" src="adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="ext-all.js"></script>
<script type="text/javascript" src="RowExpander.js"></script>
<script type="text/javascript" src="ux/grid/GridFilters.js"></script>
<script type="text/javascript" src="ux/grid/filter/Filter.js"></script>
<script type="text/javascript" src="ux/grid/filter/ListFilter.js"></script>
<script type="text/javascript" src="vars.js"></script>
<script type="text/javascript" src="repDetails.js"></script>
<!-- ENDLIBS -->

<!-- the loading indicator -->
<script type="text/javascript">
var myMask = new Ext.LoadMask(Ext.getBody(), { removeMask: true });
myMask.show();
</script>

<script type="text/javascript">
Ext.onReady(function()
{
// myData declared in vars.js
myData = [
<%-- Get the value of each column while iterating over rows --%>
<c:forEach items="${results.rowsByIndex}" var="row" varStatus="status">
[${row[0]},'${row[1]}','${row[2]}']<c:if test="${!status.last}">,</c:if>
</c:forEach>
];

var Exercise = Ext.data.Record.create([
{name: 'exerID', type: 'int'},
{name: 'exerName'},
{name: 'bench'}
]);

var myReader = new Ext.data.ArrayReader({}, Exercise);

// exerstore declared in vars.js
exerstore = new Ext.data.Store({
proxy: new Ext.data.MemoryProxy(myData),
reader: myReader,
sortInfo: { field: "exerName", direction: "ASC" }
});
...
// large section excluded for defining grids and viewport
...
// Init the singleton. Any tag-based quick tips will start working.
Ext.QuickTips.init();

// Apply a set of config properties to the singleton
Ext.apply(Ext.QuickTips.getQuickTip(), {
showDelay: 50,
dismissDelay: 0,
animCollapse: false,
trackMouse: true,
mouseOffset: [10, 10]
});

myMask.hide();
});//end onReady function
</script>
</body>
</html>


then inside repDetails.js, exerstore is trying to be used in a form's combo box:



// repDetailsPanel declared in vars.js
repDetailsPanel = new Ext.Panel(
{
layout: 'border',
id: 'repPanel',
bodyStyle: blankBgStyle,
items: [
// repDetailsForm declared in vars.js
repDetailsForm = new Ext.form.FormPanel(
{
id: 'repDetailsForm',
region: 'north',
url: 'saveRep.jsp',
method: 'POST',
onSubmit: Ext.emptyFn,
monitorValid: true,
defaultType: 'numberfield',
labelAlign: 'top',
buttonAlign: 'left',
bodyStyle: blankBgStyle,
items: [
{
name: 'workoutID',
xtype: 'hidden'
},
{
name: 'repID',
xtype: 'hidden'
},
{
// THIS is the combo box in question!
fieldLabel: 'Exercise',
hiddenName: 'exerciseID',
tabIndex: 1,
id: 'exCombo',
xtype: 'combo',
allowBlank: false,
forceSelection: true,
typeAhead: true,
triggerAction: 'all',
selectOnFocus: true,
lazyInit: true,
lazyRender: true,
anchor: '65%',
mode: 'local',
store: exerstore, // NOTE the use of the grid's store
valueField: 'exerID',
displayField: 'exerName'
},
{
fieldLabel: 'Weight',
name: 'weight',
allowBlank: false,
allowDecimals: false,
allowNegative: false,
maxLength: 3,
selectOnFocus: true,
tabIndex: 2,
validationDelay: 100,
width: 32
},
{
fieldLabel: 'Reps',
name: 'lifts',
allowBlank: false,
allowDecimals: false,
allowNegative: false,
maxLength: 2,
selectOnFocus: true,
validationDelay: 100,
tabIndex: 3,
width: 25
}
],
buttons: [
{
text: 'Save',
tooltip: 'Saves your changes',
formBind: true,
handler: function()
{
repDetailsForm.getForm().submit(
{
waitMsg: 'Saving...',
success: function(f, action)
{
if(f.getValues().repID == 0)
{
f.setValues({ repID: 0, exerciseID: '', weight: '', lifts: '' });
}
repsStore.reload();
}
});
}
},
{
text: 'Cancel',
tooltip: 'Cancels your changes and closes the form',
handler: function()
{
spanel.collapse();
spanel.setTitle("Query Results");
spanel.getLayout().setActiveItem('qresults');
}
}]
}),
new Ext.Panel({
region: 'center',
bodyStyle: blankBgStyle
})
]
});


then what is the loading sequence or the order in which things execute? I guess I'm confused over when Ext.onReady() is executed compared to other script code inside the same file but not in that function AND code from included script files.

Also, what is the basic feeling of putting all component definitions inline in one large html file versus each in its own js file and including all the files in the main html page?

I know script is typically included in <head> but for any of my stuff to work it had to go in <body> probably to make the loading mask work and hide properly. Is this correct?

And finally, if I have 2 components that both use an HttpProxy store pointing to the same URL and retrieving the same data but viewing it differently - a grid can add a filter to only show certain rows while a combobox always shows all for example - can they use the same store to prevent 2 separate AJAX calls to the server? Is there a way to do one fetch of the data and use it to update 2 stores so one component's filter doesn't affect the other? Or is there a way to accomplish the independent views with a single store?

I know I'm asking a lot of seemingly basic questions but I feel I'm on the verge of grasping this wonderful library and want to make sure I don't start off with wrong or bad habits with it. I've learned a lot and just need these few things to get over my learning curve threshold so I can start contributing back and hopefully be able to help others.

luv2hike
22 Feb 2008, 7:34 AM
Quick update: I figured something out but would still like a technical explanation as to why I'm seeing what I am so I'll know the correct sequence in the future. I got it to work by simply moving the store definition outside of the Ext.onReady() function and BEFORE the include containing the combo box. The relevant piece with changes highlighted follows:



<body>
<!-- LIBS -->
<script type="text/javascript" src="adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="ext-all.js"></script>
<script type="text/javascript" src="RowExpander.js"></script>
<script type="text/javascript" src="ux/grid/GridFilters.js"></script>
<script type="text/javascript" src="ux/grid/filter/Filter.js"></script>
<script type="text/javascript" src="ux/grid/filter/ListFilter.js"></script>
<!-- form include used to be here -->
<script type="text/javascript" src="playvars.js"></script>
<script type="text/javascript" src="query.js"></script>
<!-- ENDLIBS -->

<!-- the loading indicator -->
<script type="text/javascript">
var myMask = new Ext.LoadMask(Ext.getBody(), { removeMask: true });
myMask.show();

// now the store definition is here, outside onReady
// also replaced JSTL calls with static data for testing and posting
myData = [
[27,'AA and once again','incline'],
[44,'AA Another test','rowing'],
[11,'Ab Crunch','flat'],
[31,'AB new event handler','rowing'],
[32,'Again...','rowing'],
[25,'AND and again','incline'],
[50,'And now make it paint','squat'],
[22,'Another new key 2','rowing'],
[24,'another new one','incline'],
[46,'AY huh Do it Now','incline'],
[6,'Bench Press','incline'],
[13,'Chinups','squat'],
[33,'Did it finally work?','rowing'],
[29,'Double Commit','flat'],
[36,'Final Sorting Test','leg'],
[49,'Fix sort error and Repaint','flat'],
[17,'Friday 1','leg'],
[18,'Friday 2','rowing'],
[21,'Get the key','flat'],
[8,'Leg Extension','leg'],
[7,'Leg Press','rowing'],
[1,'Lying Biceps Curl','flat'],
[2,'Lying Shoulder Press','flat'],
[54,'MIDNIGHT','--'],
[23,'new one','flat'],
[38,'Now without a sort','squat'],
[26,'one more time','incline'],
[14,'pushups','flat'],
[37,'Really last sort test','incline'],
[3,'Rear Deltoid Rows','flat'],
[4,'Reverse Fly','flat'],
[53,'rock on','--'],
[10,'Seated Ab Crunch','incline'],
[9,'Seated Shoulder Press','flat'],
[5,'Seated Triceps Extension','incline'],
[48,'Slimline','incline'],
[12,'Squat','squat'],
[19,'Test add 1','rowing'],
[20,'test add 2','flat'],
[39,'Test Commit single','flat'],
[34,'Test the sort','flat'],
[35,'testing sort again','rowing'],
[15,'the first test','incline'],
[16,'Thursday night test','incline'],
[40,'Tuesday 1','flat'],
[41,'Tuesday 2','leg'],
[42,'Tuesday 3','squat'],
[52,'wbyp','--'],
[47,'ZZ Top','squat']
];

Exercise = Ext.data.Record.create([
{name: 'exerID', type: 'int'},
{name: 'exerName'},
{name: 'bench'}
]);

myReader = new Ext.data.ArrayReader({}, Exercise);

exerstore = new Ext.data.Store(
{
proxy: new Ext.data.MemoryProxy(myData),
reader: myReader,
autoLoad: true,
sortInfo: { field: "exerName", direction: "ASC" }
});
</script>

// this was moved down to here so it's after the store definition
<script type="text/javascript" src="playrepDetails.js"></script>

<!-- include layout AFTER the loading indicator -->
<div id="work"></div>
<div id="exer"></div>
<div id="queryDiv"></div>

<!-- for grid filter combo box -->
<select id="benchposID" style="display: none;">
<option value="--">--</option>
<option value="flat">flat</option>
<option value="incline">incline</option>
<option value="leg">leg</option>
<option value="rowing">rowing</option>
<option value="squat">squat</option>
</select>

<!-- layout screen -->
<script type="text/javascript">
Ext.onReady(function()
{
// store definition used to be here
...

While this works, it does still pose the issue of the combo box not showing all choices when the user filters a column of the grid that uses the same store. So it seems the combo box needs its own store but 2 http requests for the same data seems expensive to me. There must be another way.

And from this appears the order of execution is top down in the main file, running the script in the includes as it gets to them, with Ext.onReady() being held off to run last, even after any script that may be located AFTER it in the source. Is this accurate?

It also works if I put the store definition into its own js file and include it before the playrepDetails.js file containing the combobox. So what is "better"? Is it preferable to define everything in one file or each "piece" in several smaller js files?