PDA

View Full Version : Various data store and form extensions.



curzonj
3 Dec 2007, 12:18 PM
I have been building a big project and have build numerous Ext 2.0 extensions for data stores, some new form fields, and some components that make it really easy to work with Rails models via REST controllers. I just pulled this out of my project and haven't had time to spruce it up so please let me know if I can make it more useful or more generic. My full explanation is on my blog right now, "ExtJS customizations (http://richfrog.blogspot.com/2007/12/extjs-customizations.html)", and the code is at:

https://svn.surgeworks.com/public/extjs/trunk/

I'll add more information about the individual items and some examples as I have time.

apaa
3 Dec 2007, 11:14 PM
can you post some example about your treecombox,I want to use it,but I don't know which params I have to post to it,and I have found some bug.
like :
tree_combo.js line 36



this.nodes.store = this.store;

and the plugin:line 38


plugins: new Ext.ux.tree.DataStoreBacking(this.nodes),

I console.dir(config);I haven't got anything...,
and the store....

galdaka
4 Dec 2007, 2:17 AM
Can you post any examples about all?

curzonj
4 Dec 2007, 5:43 AM
galdaka: Sorry for the lack of examples, I just wanted to get this stuff out there. I will post exmples for everything, obviously getting to the those items that people are interested in first. Is there something specific you are interested in?

apaa: In my project everything is based around Ext.data.Record and Store. DataStoreBacking is something of a loader that builds a TreePanel and keeps the node tree up-to-date with the data store. It isn't implemented as a TreeLoader because it doesn't really fit that pattern.

TreeComboBox currently depends on DataStoreBacking in multiple ways and requires a data store. I could fix that you need me too. A piece of my working code is:


items: [
new TreeComboBox({
fieldLabel: 'Location',
hiddenName: 'portion[location_id]',
dataIndex: 'location_id',
store: locations_ds,
nodes: { textField: 'title' },
displayField: 'full_title',
valueField: 'id',
allowBlank: false,
width: 280,
resizable: true,
})
]
Here the code is assuming that your records have fields "id" and "parent_id". You can changes that by setting idField and parentIdField on the nodes attribute passed it. (nodes is a config object passed to DataStoreBacking) DataStoreBacking doesn't depend on any of my other code, but because it is based on a data store, you can use the plugins to keep the tree up to date.

All the parameters except nodes, store, and allowBlank function exactly like the regular ComboBox. Nodes is a config object passed in to DataStore backing. Store gets set on DataStoreBacking. I just changed it so you can pass it in either as a member of the nodes hash or the rest of the config options. AllowBlank shows the root node and tries it's best to be "blank" when you select the root node. That part may not function as expected, let me know and I'll fix it.

DataStoreBacking can take several parameters, only textField is required. textField is the field on the records to put as the text attribute on the tree nodes. Optional parameters are: idField and parentIdField are attributes on the records used to build the parent child relations of the tree nodes. qtipField sets the qtip on the nodes to the appropriate value from the record. baseAttrs are applied to each node just like the TreeLoader.

This is my first time really working with people outside my own shop, so please let me know if I need to do something better. Let me know if you need any changes, more examples.

curzonj
4 Dec 2007, 6:26 AM
A quick example of CRUDGridPanel is below. CRUDGridPanel is meant to have basic CRUD features with the following config, but also to be overrided in numerous ways. The "editor" parameter creates an instance of CrudEditor which has a huge set of dependecies on the response that comes back. The editor posts the form just as any form would be posted, but it expects a json object back of roughly the following format:


{
"success": (boolean, whether the record saved on the server side.
"hidden": (boolean, should the object be removed from the data store),
"objectid": (id of the record new or old),
"data": (new value of the data property on the record that was update/created),
"errors":an errors hash for BasicForm to display errors on the form
}For deletes the CrudEditor currently uses the restfull semantics "DELETE /outside_process/3". By default it bases this off the url of the data store, but you change change that by setting deleteUrl. This part of the is pretty tightly tied to a restful setup on rails. If people will explain how they'd like it to work I can make it more flexible. Here is my most basic usage of CRUDGridPanel and CrudEditor:



new CRUDGridPanel({
title: 'Outside Processes',
store: outside_processes_ds,
autoSizeColumns: true,
cm: new Ext.grid.ColumnModel([
{header: 'Number', dataIndex: 'process_number', width:70, sortable:true},
{header: 'Name', dataIndex: 'name', width:70, sortable:true}
]),

btnConfigs: [{
text: 'Delete',
handler: CRUDGridPanel.prototype.onClickDeleteBtn
}],

editor: {
height: 480,
formPanel: new Ext.form.FormPanel({
labelAlign: 'right',
buttonAlign: 'center',
height: 100,
items: [
new Ext.form.TextField({
fieldLabel: 'Name',
name: 'outside_process[name]',
dataIndex: 'name',
allowBlank: false,
}),
new Ext.form.NumberField({
fieldLabel: 'Number',
name: 'outside_process[process_number]',
dataIndex: 'process_number',
allowDecimals: false,
allowNegative: false,
allowBlank: false,
}),
new Ext.form.TextArea({
height: 130,
width: 300,
fieldLabel: 'Description',
name: 'outside_process[description]',
dataIndex: 'description',
})
]
})
}
});
});
Sorry for the terse explanation, but this is a large code base that I have never had to explain to anyone before.

apaa
6 Dec 2007, 8:03 PM
can you give me a demo? because I use it as your follow,but it didn't show anything,and there are some syntax error in ie,.......
thank you for your hard work!!!

apaa
9 Dec 2007, 6:15 PM
bd.createChild({tag: 'h2', html: 'Form 1 - Very Simple'});

var store = new Ext.data.Store({
url : 'http://tm.olerp.net/category/view?type=product&id=0&jtype',
reader : new Ext.data.JsonReader({
root : 'rows',
id : 'id'
},['id','text'])
});

var simple = new Ext.FormPanel({
labelWidth: 75, // label settings here cascade unless overridden
url:'save-form.php',
frame:true,
title: 'Simple Form',
bodyStyle:'padding:5px 5px 0',
width: 350,
defaults: {width: 230},
defaultType: 'textfield',

items: [new TreeComboBox({
fieldLabel: 'Location',
hiddenName: 'text',
dataIndex: 'text',
store: store,
nodes: { textField: 'text' },
displayField: 'text',
valueField: 'id',
allowBlank: false,
width: 280,
resizable: true
}),{
fieldLabel: 'First Name',
name: 'first',
allowBlank:false
},{
fieldLabel: 'Last Name',
name: 'last'
},{
fieldLabel: 'Company',
name: 'company'
}, {
fieldLabel: 'Email',
name: 'email',
vtype:'email'
}, new Ext.form.TimeField({
fieldLabel: 'Time',
name: 'time',
minValue: '8:00am',
maxValue: '6:00pm'
})
],

buttons: [{
text: 'Save'
},{
text: 'Cancel'
}]
});

simple.render(document.body);


the response data:


{"rows":[{"id":"4737ef6b-6c84-4088-abb3-6e39c0a80005","leaf":false,"text":"haha123"},{"id":"4737f6c3-83dc-40a7-a87f-7268c0a80005","leaf":false,"text":"\u4f60\u597d\u5446674566"},{"id":"4738405b-4b64-4056-ae35-7bfbc0a80005","leaf":false,"text":"edit ok123454"},{"id":"47381a7d-0c2c-4aac-aeaf-7473c0a80005","leaf":false,"text":"kk"},{"id":"474f8ed2-38e4-4296-8c87-1e04c0a80005","leaf":false,"text":"5566"},{"id":"4757a13d-2f04-406b-996b-19fcc0a80005","leaf":true,"text":"123453"}]}

what's wrong with it ?
anybody give me some advise?

curzonj
10 Dec 2007, 7:51 AM
apaa, I put your code together in an html page and put the data in a file and everything works fine for me. I put my test (html and data) in the attached zip file. Let me know if it gives you problems.

I just realized that if the code you posted is the actual code you used, it won't work. The parameters to your store don't look correct. It looks like you wanted to use a JsonStore and got confused. Here is the store that I used in the zip file:


var store = new Ext.data.JsonStore({
url: "data.json",
id: 'id',
root: 'rows',
fields: [ 'id', 'text' ]
});

curzonj
10 Dec 2007, 11:25 AM
If you want the tree to behave like a tree (with child nodes). Use the add "parent_id" to your fields on your data store as below. You can change the record field that links to the parent with the parentIdField configuration parameter. The field to use as the id to match parent to child can be changed with the idField config parameter (both to be set on the TreeComboBox.


var store = new Ext.data.JsonStore({
url: "data.json",
id: 'id',
root: 'rows',
fields: [ 'id', 'text', 'parent_id' ]
});And change your data so each row has a parent_id for the node which it is a child of:



"rows":[

{"id":"4737ef6b-6c84-4088-abb3-6e39c0a80005","leaf":false,"text":"haha123", "parent_id":null},
{"id":"4737f6c3-83dc-40a7-a87f-7268c0a80005","leaf":false,"text":"d5446674566", "parent_id":null},
{"id":"4738405b-4b64-4056-ae35-7bfbc0a80005","leaf":false,"text":"edit ok123454", "parent_id":null},

{"id":"47381a7d-0c2c-4aac-aeaf-7473c0a80005","leaf":false,"text":"kk", "parent_id":"4737f6c3-83dc-40a7-a87f-7268c0a80005"},
{"id":"474f8ed2-38e4-4296-8c87-1e04c0a80005","leaf":false,"text":"5566", "parent_id":"4737f6c3-83dc-40a7-a87f-7268c0a80005"},
{"id":"4757a13d-2f04-406b-996b-19fcc0a80005","leaf":true,"text":"123453", "parent_id":"4737ef6b-6c84-4088-abb3-6e39c0a80005"}

]

As a side note, because the data store is building your parent child relationships for you, you don't need (nor does it do anything) to have the leaf attribute on your records.

disfusion
19 Dec 2007, 10:32 PM
curzonj

Does the TreeComboBox handle multiple children nodes? As in more than 2 levels.

E.G 3 Levels
Parent Node 1
|-Child Node A of Parent 1
| |- Child Node 1 of Child Node A
| |- Child Node 2 of Child Node A
|-Child Node B of Parent 1
| |- Child Node 1 of Child Node B
| |- Child Node 2 of Child Node B
Parent Node 2
|-Child Node C of Parent 2
| |- Child Node 1 of Child Node C
| |- Child Node 2 of Child Node C

Or even more levels?

I seem to get an error if I add third level nodes

Thanks

curzonj
20 Dec 2007, 12:20 AM
disfusion: It should handle it just fine. Your parent id's just need to be sett to the correct parent, and it's done. I use it for trees that are very deep. If you could post the error you get and some sanitized data that can reproduce the error, I'll take a look at it.

cocorossello
21 Dec 2007, 3:21 AM
Thx for sharing :D

I'll figure out how to use it, I was about to do the same CRUDGridPanels

disfusion
21 Dec 2007, 3:40 PM
curzonj

I have got it working, the problem was actually caused by 2 errors in the js files. FF seem didn't seem to throw any errors about them, but IE did.

tree_combo.js - extra comma at the end of line 47 should not be there
data_store_tree.js - extra comma at the end of line 147 should not be there

Fixed those and it seems to be working now.

Thanks

Elkmor
23 Dec 2007, 4:45 AM
curzonj, thank you for this public release, it is very interesting

curzonj
23 Dec 2007, 7:39 AM
disfusion, Thanks for those fixes. I have checked them into the source.

Thomas_K
29 Dec 2007, 2:22 AM
any idea how i can set a value onload?
nothing defined right now?

curzonj
29 Dec 2007, 5:51 AM
any idea how i can set a value onload?
nothing defined right now?

The only component I assume you could be refering to is the CrudEditor (which wraps a form). Crud Editor has two methods: beforeload and load. It also relays the form events of beforeaction, actionfailed, and actioncomplete. If you are using the TabbedCrudEditor, make sure the form the event fired on is the form you want.

Here is an example of how to use the load action to set values in the form just before show() is called on the dialog:


editor.on('load', function(form, record) {
form.findField('portion[notes]').setValue("This is the value of the form field");
});Here is an example of using the 'beforeload' method to set some defaults:


editor.on('beforeload', function(form, record) {
if(record.newRecord) {
//Load defaults. You could use record.set() here if you wanted to.
record.data.runtime_markup = 100
record.data.setup_markup = 100
record.data.programming_markup = 100
}
});Using the the load and beforeload actions you can customize the form a lot. To customize other parts of it's behavior, my situations have each been so unique that I haven't made events for anything else, I just override functions when I need heavy one-off customizations. I do such customizations frequently because I use the editor to represent the data models in my javascript and so they are pretty tightly bound. Let me know if you would like some more events added, because I assume others would benefit.

Does that answer your question?

galdaka
29 Dec 2007, 9:53 AM
Hi,

Is posible view a live demo of treecombobox?


Thanks in advance,

DigitalSkyline
31 Dec 2007, 5:16 PM
Nevermind... the issue was elsewhere...

Still having a problem but I think it might be an issue with the JSON format used to create the store... still investigating.



BTW Happy New Years!

attiato
7 Jan 2008, 1:43 AM
1. How can I put a loadMask for the tree_combo?
2. Is there a timout for the store response, because not always is waiting for the response from the server side script?
Thanx in advance,

curzonj
7 Jan 2008, 5:43 AM
Anyone that wants a live demo for any of the other things in my svn repo, just let me know, I can build those easily now.

Galdaka: I have put put a live demo of the TreeComboBox at:

http://splashnetworks.net/demos/treecombo.html

Attiato: To create a load mask you'll need to do it by hand. You can create a load mask on any data store with the following:


var mask = new Ext.LoadMask( treeCombo.innerList, { store: treeCombo.store });
I don't really understand your second sentence, but as far as a timeout goes. HttpProxy uses Ext.Ajax so if you could use:


Ext.Ajax.timeout = 10000;That is in ms (10000 = 10sec), the default is 30000 (30sec).

Let me know if that answered your question.

attiato
7 Jan 2008, 9:09 AM
curzonj:

Can you give me some more code for the loadMask? where to put

var mask = new Ext.LoadMask( treeCombo.innerList, { store: treeCombo.store });

in the tree_combo.js file, other file, or my own, where i declare the store?
My code has something like this:


var pStore = new Ext.data.JsonStore({
url: "../groups",
id: 'id',
root: 'rows',
fields: [ 'id', 'text', 'parent_id' ]
});

pStore.on('loadexception', function() {
alert('error');
});

var parentGroup = new Ext.ux.TreeComboBox({
fieldLabel: 'Parent Group',
hiddenName: 'parent_id',
dataIndex: 'text',
store: pStore,
nodes: { textField: 'text' },
displayField: 'text',
valueField: 'id',
allowBlank: true,
resizable: true,
rootVisible:true,
name: 'groupName',
triggerAction:'all',
anchor: '70%'
});

curzonj
7 Jan 2008, 9:53 AM
I looked at the code more closely and it will take more work that what I told you. Be aware, I have not tried this so you may have to work through some issues on your own. Because the innerList is created dynamically on focus, there are no events that fire in between the innerList being created and in being shown. So you'll have to override the initList method. I have modified your code as I think it should be:



var parentGroup = new Ext.ux.TreeComboBox({
fieldLabel: 'Parent Group',
hiddenName: 'parent_id',
dataIndex: 'text',
store: pStore,
nodes: { textField: 'text' },
displayField: 'text',
valueField: 'id',
allowBlank: true,
resizable: true,
rootVisible:true,
name: 'groupName',
triggerAction:'all',
anchor: '70%',
initList: function() {
Ext.ux.TreeComboBox.prototype.call(this);
this.loadMask = new Ext.LoadMask(
this.innerList,
{
store: pStore
}
);
/* The reason for this code is that
the load mask functions via an on('load', ...)
event listener and I assume that when
the combo box list is being shown, you
have already called store.load()
*/
if(this.store.proxy.activeRequest) {
this.loadMask.show();
}
}
});
Be aware that I have used the loadMask in similar situations where I had to trigger it manually, but it was a bit unpredictable. There may not be a reliable way to use the loadMask in this situation.

mujahid
10 Jan 2008, 7:05 AM
Will the TreeComboBox support multiple selections in the tree?

curzonj
10 Jan 2008, 7:55 AM
Will the TreeComboBox support multiple selections in the tree?

Not really. Like the combobox it is designed to support many single-selection features that don't work with multiselect.

DDBulkMultiselect might work for you. It is two trees next to each other. One is the selected items and one is the unselected. Right now it doesn't do nesting of objects (just a list using the tree widget), but that is only because I haven't implemented it yet. You just drag and drop items from one tree to another and then the widget saves a csv of the idField values to a hidden field.

mdissel
15 Jan 2008, 4:52 AM
I see that you created a extbugfixes file. Are these fixes still valid or already solved in the Ext trunk svn version?

Thanks

Marco

curzonj
15 Jan 2008, 5:11 AM
I see that you created a extbugfixes file. Are these fixes still valid or already solved in the Ext trunk svn version?

Thanks

Marco

I don't know. As far as I understand only premium members have access to the svn version. They are valid against the 2.0-final and I haven't reported them to anyone. Originally I had some real bugs in there, but they got fixed in 2.0 final. The remaining items are a bit subjective whether they are bugs or not, so I don't worry about submitting them.

midnite_cowboy
23 Jan 2008, 6:15 AM
Could you post some working examples/demos of the CrudGridPanel? I've been trying (from the examples you've already posted) for a couple of days but still can get it to work. I keep getting errors about the store.

Thanks in advance

curzonj
23 Jan 2008, 6:44 AM
The grid panel uses a set of enhancements on the store that are in the SWorks.CrudStore class. It is a subclass of GroupingStore, but it's internal code behaves like JsonStore as far as creating the proxy and reader. I can fix to to allow you to pass in your own reader and/or proxy, I just haven't needed to. You can read the code for both in crud_components.js, it should be pretty straight forward.


var myStore = new SWorks.CrudStore({
.... (Normal JsonStore stuff),
fields: [ 'description', .... ]
});
var myGrid = new SWorks.CrudGridPanel({
title: "Widgets",
store: myStore,
columns: [
{header: 'Description', dataIndex: 'description'}
]
});

That is obviously the bare minimum and without the CrudEditor config normally passed in on the "editor" property. Maybe the best thing would be for you to post your code and what errors you are getting and I could tell you where to go from there. Unfortunately, my code still has a large number of assumptions that need to get worked out.

midnite_cowboy
23 Jan 2008, 7:38 AM
Thanks for answering so soon.
In my previous attempts I was using a regular Store, and got a "this.store has no properties" error.
As you suggested, I tried to get a minimal example to work, but still get "has no properties" related errors. In this particular case:

"SWorks.CurrentUser has no properties"

Crud_Components.js Line 154:
SWorks.CurrentUser.onPermission(this.store.rwPerm, this.checkToolbarButtons, this);




Ext.onReady(function() {

var storex = new SWorks.CrudStore({
url: 'json.data',
id: 'name',
root: 'rows',
fields: [name]
});

var myGrid = new SWorks.CrudGridPanel({
title: "Simplest",
store: storex,
columns: [
{header: 'Name', dataIndex: 'name'}
]
});

curzonj
23 Jan 2008, 8:03 AM
Well, you have happened upon one of it's worst assumptions. I'll try and clean that up to later tonight. The Crud store deals with permissions too, and uses the SWorks.CurrentUser singleton to do so.

midnite_cowboy
24 Jan 2008, 3:58 AM
Hi. On the code I posted the editor configuration is missing. I think that's why the CurrentUser error popped up. I fixed it, but still get a "this.store has no properties" error.

file: crud_editor.js Line 21:
if(this.store.loadIfNeeded)

I post the complete source, including the JS included (maybe the problem lies there, somehow...)



<script src="adapter/ext/ext-base.js" type="text/javascript"></script>
<script src="ext-all.js" type="text/javascript"></script>
<script src="framework/ext_bug_fixes.js" type="text/javascript"></script>
<script src="framework/ext_overrides.js" type="text/javascript"></script>
<script src="framework/data_stores.js" type="text/javascript"></script>
<script src="framework/data_store_tree.js" type="text/javascript"></script>
<script src="framework/crud_components.js" type="text/javascript"></script>
<script src="framework/crud_editor.js" type="text/javascript"></script>


<script type="text/javascript">

Ext.onReady(function() {

var storex = new SWorks.CrudStore({
url: 'json.data',
id: 'name',
root: 'rows',
fields: [name]
});

var simple = new SWorks.CrudGridPanel({
title: "Simplest",
store: storex,
columns: [
{id: 'Name', header: 'Name', dataIndex: 'name'}
],
editor: {
height: 480,
formPanel: new Ext.form.FormPanel({
labelAlign: 'right',
buttonAlign: 'center',
height: 100,
store: storex,
items: [
{
fieldLabel: 'Name',
name: 'Idusr',
allowBlank:false
}
]
})
}
});

//simple.store.load(); Commented to narrow possible error sources
//simple.render(Ext.getBody()); same as above


Thanks again.

lostAtSea
30 Jan 2008, 7:49 AM
Hello,

I'm using your data store tree class and everything is work fine except that I can't work out how to update a record in the store without triggering 'too much recursion' errors. I'm using the set method of the selected record.

Thanks.

[update]
Sorry the issue was due to my misunderstanding the sequence of events when a store record is updated.

lostAtSea
1 Feb 2008, 4:25 AM
There seems to be a minor bug in the latest version of data_store_tree.js
line 87

for(var i2=0;i<remove.length;i++) {should be

for(var i2=0;i2<remove.length;i2++) {

mujahid
1 Feb 2008, 5:56 AM
Does TreeCombo supports lazy loading like a tree loader?

infinit
13 Mar 2008, 1:01 AM
I set up the example as the demo does. (http://splashnetworks.net/demos/treecombo.html)

the TreeComboBox can't display, and there are two errors:
data_stores.js( line 110), Ext.ux.data has no properties
Ext.ux.data.LoadAttempts = function(store, maxAttempts) {
tree_combo.js( line 65), Ext.ux.tree.DataStoreBacking is not a constructor
plugins: new Ext.ux.tree.DataStoreBacking(this.nodes),
Can anyone help to fix this, thanks.

curzonj
13 Mar 2008, 6:34 AM
I set up the example as the demo does. (http://splashnetworks.net/demos/treecombo.html)

the TreeComboBox can't display, and there are two errors:
data_stores.js( line 110), Ext.ux.data has no properties
Ext.ux.data.LoadAttempts = function(store, maxAttempts) {
tree_combo.js( line 65), Ext.ux.tree.DataStoreBacking is not a constructor
plugins: new Ext.ux.tree.DataStoreBacking(this.nodes),
Can anyone help to fix this, thanks.

Yea, the issue is that I don't know how to best setup the name spaces so I did it in one of the other files (ext_overrides.js) I think. If you don't use all the files, you just need to defined the Ext.ux.data namespace yourself before loading data_stores.js.

curzonj
13 Mar 2008, 6:44 AM
Everyone should know that Ext has released its own version of the TreeComboBox with the Simple Tasks v2 and Ext 2.0.2 called a ListTree. http://extjs.com/blog/2008/02/24/tasks2/

infinit
13 Mar 2008, 8:06 AM
Yea, the issue is that I don't know how to best setup the name spaces so I did it in one of the other files (ext_overrides.js) I think. If you don't use all the files, you just need to defined the Ext.ux.data namespace yourself before loading data_stores.js.

curzonj, thanks for your help, can you explain more in detail about how to do this? thanks.

infinit
13 Mar 2008, 7:14 PM
I found another issue after got it running:
ext_overrides.js (line 24), CSRFKiller is not defined,

options.params = CSRFKiller.field+'='+CSRFKiller.token;

This happens when I submit the form.

6epcepk
6 May 2008, 1:57 AM
Hi, thx 4 ux!
I try to use ux with this config:

var categoryDs = new Ext.data.Store({
proxy: new Ext.data.HttpProxy({
url: 'index.php?load=modules/catalog/categories/data/select.php'
}),
reader: new Ext.data.JsonReader({
root: 'rows',
id: 'id',
}, ['id', 'text']
),
remoteSort: false
});

categoryDs.load();

var category = new Ext.ux.TreeComboBox({
nodes: {
store: categoryDs,
textField: 'text'
},
fieldLabel: this.form.category,
hiddenName: 'portion[location_id]',
dataIndex: 'location_id',
displayField: 'full_title',
emptyText: this.form.categorySel,
valueField: 'id',
allowBlank: false,
width: 280,
resizable: true,
});

My JSON is:

({"rows":[{"id":"1","text":"\u041d\u043e\u0443\u0442\u0431\u0443\u043a\u0438","iconCls":"folder","leaf"

:false},{"id":"2","text":"\u0422\u0435\u043b\u0435\u0444\u043e\u043d\u044b","iconCls":"folder","leaf"

:false}]})

But:
1. When I clicked on item, it's not pastle to my combobox;
2. I can't select child elements with ajax query (as default with tree component);

http://img375.imageshack.us/img375/7982/60229980cp4.jpg

Thx!

rplotkin
29 May 2008, 12:13 PM
Hey there,

I am using Ext.ux.Tree.DataStoreBacking. I've added the following lines to the file to add support for filtered data stores:

within init, added

this.store.on('datachanged', this.onDataStoreReloaded, this);within reloadChildren, I now have the following code (red is new)



var parentId = this.extractRecordId(node);

//create a snapshot of the snapshot!
var tmpSnapshot = this.store.snapshot;
this.store.snapshot = this.store.data;

var records = this.store.queryBy(function(record, id) {
return (record.data && record.data[this.parentIdField] == parentId);
}, this);

//restore the store's snapshot
this.store.snapshot = tmpSnapshot;
tmpSnapshot = null;

Marshal.Lin
7 Mar 2009, 8:26 AM
can this TreeCombobox allow input a value manual and then atuo display the name when pree the ENTER key down?/or allow input manual and filter the tree?

thanks!

jamiem
20 May 2009, 4:13 AM
Hi, I 'm trying out CrudGridPanel widget but receiving the following error in firebug

this.formPanel is undefined

Here is a copy of the code I am using;


<script type="text/javascript" src="core/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="core/ext-all-debug.js"></script>
<script type="text/javascript" src="sworks/namespaces.js"></script>
<script type="text/javascript" src="sworks/ext_bug_fixes.js"></script>
<script type="text/javascript" src="sworks/ext_overrides.js"></script>
<script type="text/javascript" src="sworks/data_stores.js"></script>
<script type="text/javascript" src="sworks/crud_components.js"></script>
<script type="text/javascript" src="sworks/crud_editor.js"></script>
<script type="text/javascript" src="sworks/collection_index.js"></script>
<script type="text/javascript">
Ext.onReady(function() {
var myStore = new SWorks.CrudStore({
url: 'suppliers.php'
// fields, root, id and totalProperty are retrieved as metaData
});

myStore.load();

var name = new Ext.form.TextField({
fieldLabel: 'Supplier Name',
allowBlank: false,
name: 'supplier_name',
maxLength: 100,
anchor: '90%'
});
var contact = new Ext.form.TextField({
fieldLabel: 'Contact Name',
allowBlank: false,
name: 'contact_name',
maxLength: 50,
anchor: '90%'
});
var email = new Ext.form.TextField({
fieldLabel: 'Email',
name: 'contact_email',
vtype:'email',
blankText: '',
maxLength: 50,
anchor: '90%'
});
var myGrid = new SWorks.CrudGridPanel({
title: "Widgets",
store: myStore,
renderTo: 'binding-example',
cm: new Ext.grid.ColumnModel([
{header: "Name", width: 120, sortable: true, dataIndex: 'supplier_name'},
{header: "Contact", width: 80, dataIndex: 'contact_name'},
{header: "Telephone", width: 80, dataIndex: 'phone_number'},
{header: "Email", width: 120, dataIndex: 'contact_email'},
{header: "Fax", width: 80, dataIndex: 'fax_number'},
{header: "Website", width: 100, dataIndex: 'site_url'}
]),
editor: {
height: 480,
formPanel: new Ext.form.FormPanel({
labelAlign: 'right',
buttonAlign: 'center',
height: 100,
items: [
new Ext.form.TextField({
fieldLabel: 'Name',
name: 'supplier_name',
dataIndex: 'supplier_name',
allowBlank: false,
}),
new Ext.form.TextArea({
height: 130,
width: 300,
fieldLabel: 'Notes',
name: 'notes',
dataIndex: 'notes',
})
]
})
}
});
});
</script>


As there is no documentation or real examples I'm not sure if I am missing something.

Jordan, Is there any chance you could post how you would instantiate a crud grid using the later mvc_ classes.

jamiem
20 May 2009, 4:56 AM
I managed to get past the this.formPanel is missing after reading a clue in one of the previous posts where you need to create an instance of the CrudEditor instead of just a formPanel in the editor property as a previous poster had done.

This now loads the grid, just need to work out how the toolbar actions are setup as I'm not getting a new dialog when clicking edit.

Here is my revised code:


<script type="text/javascript" src="core/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="core/ext-all-debug.js"></script>
<script type="text/javascript" src="sworks/namespaces.js"></script>
<script type="text/javascript" src="sworks/ext_bug_fixes.js"></script>
<script type="text/javascript" src="sworks/ext_overrides.js"></script>
<script type="text/javascript" src="sworks/data_stores.js"></script>
<script type="text/javascript" src="sworks/crud_components.js"></script>
<script type="text/javascript" src="sworks/crud_editor.js"></script>
<script type="text/javascript" src="sworks/collection_index.js"></script>
<script type="text/javascript" src="sworks/account_menu.js"></script>
<script type="text/javascript" src="sworks/common_messages.js"></script>
<script type="text/javascript" src="sworks/csrf_killer.js"></script>
<script type="text/javascript" src="sworks/error_handling.js"></script>
<script type="text/javascript" src="sworks/filter_field.js"></script>
<script type="text/javascript" src="sworks/helpers.js"></script>
<script type="text/javascript" src="sworks/logging.js"></script>
<script type="text/javascript" src="sworks/navigation.js"></script>
<script type="text/javascript" src="sworks/number_field.js"></script>
<script type="text/javascript">
Ext.onReady(function() {
var myStore = new SWorks.CrudStore({
url: '/admin/suppliers.php',
reader: new Ext.data.JsonReader()
});

var name = new Ext.form.TextField({
fieldLabel: 'Supplier Name',
allowBlank: false,
name: 'supplier_name',
maxLength: 100,
anchor: '90%'
});
var contact = new Ext.form.TextField({
fieldLabel: 'Contact Name',
allowBlank: false,
name: 'contact_name',
maxLength: 50,
anchor: '90%'
});
var email = new Ext.form.TextField({
fieldLabel: 'Email',
name: 'contact_email',
vtype:'email',
blankText: 'Please provides your correct email address',
maxLength: 50,
anchor: '90%'
});

var myEditor = new SWorks.CrudEditor({
height: 480,
formPanel: new Ext.form.FormPanel({
labelAlign: 'right',
buttonAlign: 'center',
height: 100,
items: [name, contact, email]
})
});

var myGrid = new SWorks.CrudGridPanel({
title: "Widgets",
store: myStore,
height: 480,
cm: new Ext.grid.ColumnModel([
{header: "Name", width: 120, sortable: true, dataIndex: 'supplier_name'},
{header: "Contact", width: 80, dataIndex: 'contact_name'},
{header: "Telephone", width: 80, dataIndex: 'phone_number'},
{header: "Email", width: 120, dataIndex: 'contact_email'},
{header: "Fax", width: 80, dataIndex: 'fax_number'},
{header: "Website", width: 100, dataIndex: 'site_url'}
]),
editor: myEditor
});
myGrid.render(document.body);
});
</script>

jamiem
20 May 2009, 6:57 AM
this.recordType is not a constructor
crud_editor.js
Line 493

I now receive this error when attempting to add a new record

I have no idea what this.klass is about? If someone could please fill me in

Also the edit button still doesn't fire any event

kimosabi
11 Dec 2009, 7:58 AM
Thanks for posting this awesome extension. I found it easy to integrate. Guru points mate.

rasharma@quark.com
15 Jan 2010, 5:39 AM
Tree combo is exactly kind of UI we need.

I tried loading combo tree from a store so used following code for that.
But firebug keeps on giving a error. Code and error attached.





<html><head>

<script src="../../../adapter/ext/ext-base.js" type="text/javascript"></script>
<script src="../../../ext-all.js" type="text/javascript"></script>
<script src="./ext_bug_fixes.js" type="text/javascript"></script>
<script src="./ext_overrides.js" type="text/javascript"></script>
<script src="./data_stores.js" type="text/javascript"></script>
<script src="./data_store_tree.js" type="text/javascript"></script>
<link href="../../../resources/css/ext-all.css" media="screen" rel="Stylesheet" type="text/css" />

<script type="text/javascript">

/* Mostly copied from combo boxes. Ext.ux.TreeComboBox currently depends on
* DataStoreBacking in multiple ways and requires a data store. I could
* fix that you need me to. nodes is a config parameter passed to the
* DataStoreBacking.
*
* Example:
* items: [new Ext.ux.TreeComboBox({
* //Required, non-standard parameters
* nodes: {
* store: locations_ds,
* textField: 'title'
* },
* //Parameters that function exactly like the ComboBox
* fieldLabel: 'Location',
* hiddenName: 'portion[location_id]',
* dataIndex: 'location_id',
* displayField: 'full_title',
* valueField: 'id',
* allowBlank: false,
* width: 280,
* resizable: true,
* }), {
*/

/*globals Ext, SWorks, console */
/*jslint glovar: true, undef: true, nomen: true */

Ext.namespace('Ext.ux');

Ext.ux.TreeComboBox = Ext.extend(Ext.form.TriggerField, {
valueNotFoundText: "Item not found",
defaultAutoCreate : {tag: "input", type: "text", size: "24", autocomplete: "off"},
listClass: '',
selectedClass: 'x-combo-selected',
triggerClass : 'x-form-arrow-trigger',
shadow:'sides',
listAlign: 'tl-bl?',
maxHeight: 300,
resizable: false,
handleHeight : 8,
minListWidth : 70,
// If you use lazyInit, the user won't have any indication that
// the tree is loading it's data. TODO maybe we need a loading
// mask
lazyInit : false,

initComponent : function(){
Ext.ux.TreeComboBox.superclass.initComponent.call(this);
this.addEvents({
'expand' : true,
'collapse' : true,
'beforeselect' : true,
'select' : true
});
this.selectedNode = -1;

if(!this.tree) {
var root = { id: 'root' };
if(this.allowBlank) {
root.text = 'Root level';
root.expanded = true;
}

if (this.store) {
this.nodes.store = this.store;
}

this.tree = new Ext.tree.TreePanel({
plugins: new Ext.ux.tree.DataStoreBacking(this.nodes),
animate: false,
rootVisible: this.allowBlank,
autoScroll: true,
border: false,
root: new Ext.tree.TreeNode(root)
});
}
},

onRender : function(ct, position){
Ext.ux.TreeComboBox.superclass.onRender.call(this, ct, position);
if(this.hiddenName){
this.hiddenField = this.el.insertSibling({tag:'input', type:'hidden', name: this.hiddenName, id: (this.hiddenId||this.hiddenName)},
'before', true);
this.hiddenField.value =
this.hiddenValue !== undefined ? this.hiddenValue :
this.value !== undefined ? this.value : '';

this.el.dom.removeAttribute('name');
}

this.el.dom.setAttribute('readOnly', true);
this.el.on('mousedown', this.onTriggerClick, this);
this.el.addClass('x-combo-noedit');

if(!this.lazyInit){
this.initList();
}else{
this.on('focus', this.initList, this, {single: true});
}
},

initList : function(){
if(!this.list){
var cls = 'x-combo-list';

this.list = new Ext.Layer({
shadow: this.shadow, cls: [cls, this.listClass].join(' '), constrain:false
});

var lw = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth);
this.list.setWidth(lw);
this.assetHeight = 0;

if(this.title){
this.header = this.list.createChild({cls:cls+'-hd', html: this.title});
this.assetHeight += this.header.getHeight();
}

this.innerList = this.list.createChild({cls:cls+'-inner'});
this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));

this.tree.render(this.innerList);
this.tree.on('dblclick', this.onSelect, this);
var mySorter = new Ext.tree.TreeSorter(this.tree, {folderSort: true});

this.restrictHeight();

if(this.resizable){
this.resizer = new Ext.Resizable(this.list, {
pinned:true, handles:'se'
});
this.resizer.on('resize', function(r, w, h){
this.maxHeight = h-this.handleHeight-this.list.getFrameWidth('tb')-this.assetHeight;
this.listWidth = w;
this.innerList.setWidth(w - this.list.getFrameWidth('lr'));
this.restrictHeight();
}, this);
this.innerList.setStyle('margin-bottom', this.handleHeight+'px');
}
}
},

initEvents : function(){
Ext.ux.TreeComboBox.superclass.initEvents.call(this);

this.keyNav = new Ext.KeyNav(this.el, {
"esc" : function(e){
this.collapse();
},

scope : this,

doRelay : function(foo, bar, hname){
if(hname == 'down' || this.scope.isExpanded()){
return Ext.KeyNav.prototype.doRelay.apply(this, arguments);
}
return true;
},

forceKeyDown : true
});
},

onDestroy : function(){
if(this.view){
this.view.el.removeAllListeners();
this.view.el.remove();
this.view.purgeListeners();
}
if(this.list){
this.list.destroy();
}
Ext.ux.TreeComboBox.superclass.onDestroy.call(this);
},

onResize: function(w, h){
Ext.ux.TreeComboBox.superclass.onResize.apply(this, arguments);
if(this.list && this.listWidth === undefined){
var lw = Math.max(w, this.minListWidth);
this.list.setWidth(lw);
this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
}
},

onDisable: function(){
Ext.ux.TreeComboBox.superclass.onDisable.apply(this, arguments);
if(this.hiddenField){
this.hiddenField.disabled = this.disabled;
}
},

onSelect : function(node, e){
if(this.fireEvent('beforeselect', this, node, e) !== false){
this.setValue(node);
this.collapse();
this.fireEvent('select', this, node, e);
}
},

getValue : function(){
if(this.valueField){
return typeof this.value != 'undefined' ? this.value : '';
}else{
return Ext.ux.TreeComboBox.superclass.getValue.call(this);
}
},

clearValue : function(){
if(this.hiddenField){
this.hiddenField.value = '';
}
this.setRawValue('');
this.lastSelectionText = '';
this.applyEmptyText();
},

setValue : function(v){
var node = null;
if(v && v.attributes) {
node = v;
if(node.isRoot) {
v = null;
} else {
v = node.attributes.record.data[this.valueField || this.displayField];
}
}

var text = v;
// Everything is build to have a value field, it should mostly work
// without one
if(this.valueField && v){
if(!node) {
node = this.tree.findNodeBy(this.nodeMatch.createDelegate(this, [v], true));
}

if(node) {
this.node = node;
text = node.attributes.record.data[this.displayField];
this.selectNode(node);
} else {
text = this.valueNotFoundText;
}
}

if(!v && this.tree.rootVisible) {
this.selectNode(this.tree.root);
}

this.lastSelectionText = text;
if(this.hiddenField){
this.hiddenField.value = v;
}
Ext.ux.TreeComboBox.superclass.setValue.call(this, text);
this.value = v;
},

nodeMatch: function(node, value) {
return (node.attributes.record && node.attributes.record.data &&
node.attributes.record.data[this.valueField] == value);
},

selectNode: function(node) {
if(node.parentNode) {
var path = node.parentNode.getPath();

this.tree.collapseAll();
this.tree.expandPath(path);
}

node.select();
},

restrictHeight : function(){
var fw = this.list.getFrameWidth('tb');
this.innerList.setHeight(this.maxHeight);
this.list.beginUpdate();
this.list.setHeight(this.innerList.getHeight()+fw+(this.resizable?this.handleHeight:0)+this.assetHeight);
this.list.alignTo(this.el, this.listAlign);
this.list.endUpdate();
},

isExpanded : function(){
return this.list && this.list.isVisible();
},

collapse : function(){
if(!this.isExpanded()){
return;
}
this.list.hide();
Ext.getDoc().un('mousewheel', this.collapseIf, this);
Ext.getDoc().un('mousedown', this.collapseIf, this);
this.fireEvent('collapse', this);
},

collapseIf : function(e){
if(!e.within(this.wrap) && !e.within(this.list)){
this.collapse();
}
},

expand : function(){
if(this.isExpanded() || !this.hasFocus){
return;
}
this.list.alignTo(this.wrap, this.listAlign);
this.list.show();
Ext.getDoc().on('mousewheel', this.collapseIf, this);
Ext.getDoc().on('mousedown', this.collapseIf, this);
this.fireEvent('expand', this);
},

onTriggerClick : function(){
if(this.disabled){
return;
}
if(this.isExpanded()){
this.collapse();
this.el.focus();
}else {
this.onFocus({});
this.expand();
this.el.focus();
}
}
});
Ext.reg('treecombo', Ext.ux.TreeComboBox);



//<![CDATA[
Ext.onReady(function() {

Ext.getBody().createChild({tag: 'h2', html: 'Form 1 - Very Simple'});
var myData = [
[1, '3m Co',0],
[2, 'Alcoa Inc',0],
[3, 'Altria Group Inc',0],
[4, 'American Express Company',0]
];
// create the data store
var store = new Ext.data.ArrayStore({
fields: [
{name: 'id'},
{name: 'text'},
{name: 'parent_id'}
]
});
store.loadData(myData);
store.on('loadexception', function() {
alert('error');
});


var simple = new Ext.FormPanel({
labelWidth: 75, // label settings here cascade unless overridden
url:'save-form.php',
frame:true,
title: 'Simple Form',
bodyStyle:'padding:5px 5px 0',
width: 350,
defaults: {width: 230},
defaultType: 'textfield',

items: [new TreeComboBox({
fieldLabel: 'Location',
hiddenName: 'text',
dataIndex: 'text',
store: store,
nodes: { textField: 'text' },
displayField: 'text',
valueField: 'id',
allowBlank: false,
width: 280,
resizable: true
}),{
fieldLabel: 'First Name',
name: 'first',
allowBlank:false
},{
fieldLabel: 'Last Name',
name: 'last'
},{
fieldLabel: 'Company',
name: 'company'
}, {
fieldLabel: 'Email',
name: 'email',
vtype:'email'
}, new Ext.form.TimeField({
fieldLabel: 'Time',
name: 'time',
minValue: '8:00am',
maxValue: '6:00pm'
})
],

buttons: [{
text: 'Save'
},{
text: 'Cancel'
}]
});

simple.render(Ext.getBody());
});

//]]>
</script>

</head>
<body><body>
</html>




Firebug keeps on giving error



TreeComboBox is not defined
file:///Users/rasharma/Desktop/extjs/ext-3.0.0/examples/form/curzonj-ext-extensions-9106ec7/test.html
Line 378


Thanks
Regards..

cedlabal
16 Jul 2010, 2:43 AM
hi all,
i try to set the value of my combotree, but it seem that it does not work!
In setValue function , there is a "findNodeBy" trying to set the node if value to set is a value and not a node, but this function doesn't exist anywhere !
Is someone try to set a value with success ?

thx

rogerio.carrasqueira
21 Dec 2010, 5:50 PM
Hi Everybody!

I'm having the same problem! Can someone have the solution?

this.tree.findNodeBy is not a function

herist
29 Jul 2011, 1:30 AM
Hi:
I found the CellAction column has a text-overflow problem in IE 6.
I use extjs 3.2 .