Implementing a ComboTree extension
Hi guys,
as i`ve already posted here I need a ComboTree component for my application.
I am now trying to implement the extension on myself within the Ext.UX project.
I`ve compiled my customized extension library successfully and the control is showing up in my application.
However, when i expand a node within the tree popup the assigned TreeLoader event is never raised server-side.
A request to the server is made, but it fails with an error message ("control ext-gen1000 not found").
Here is my code:
ComboTree.js
Code:
Ext.namespace('Ext.ux');
/**
*
* @class ComboTree
* @extends Ext.form.ComboBox
*/
Ext.ux.ComboTree = Ext.extend(Ext.form.ComboBox, {
extStore: null,
tree: null,
treeId: 0,
setValue: function(v) {
var text = v;
if (this.valueField) {
var r = this.findExtRecord(this.valueField, v);
if (r) {
text = r.data[this.displayField];
} else if (this.valueNotFoundText !== undefined) {
text = this.valueNotFoundText;
}
}
Ext.ux.ComboTree.superclass.setValue.call(this, text);
this.lastSelectionText = text;
if (this.hiddenField) {
this.hiddenField.value = v;
}
this.value = v;
},
initComponent: function() {
this.treeId = Ext.id();
this.focusLinkId = Ext.id();
Ext.apply(this, {
store: new Ext.data.SimpleStore({
fields: [],
data: [[]]
}),
editable: false,
shadow: false,
mode: 'local',
triggerAction: 'all',
maxHeight: 200,
tpl: '<tpl for="."><div style="height:200px"><div id="'
+ this.treeId + '">
</tpl>',
selectedClass: '',
onSelect: Ext.emptyFn,
valueField: 'id'
});
var treeConfig = {
border: false,
rootVisible: true,
loader: this.loader // loader is assigned here
};
Ext.apply(treeConfig, this.treeConfig);
if (!treeConfig.root) {
treeConfig.root = new Ext.tree.AsyncTreeNode({
text: 'treeRoot',
id: '0'
});
}
this.tree = new Ext.tree.TreePanel(treeConfig);
this.on('expand', this.onExpand);
this.tree.on('click', this.onClick, this);
Ext.ux.ComboTree.superclass.initComponent.apply(this,
arguments);
},
findExtRecord: function(prop, value) {
var record;
if (this.extStore != null) {
if (this.extStore.getCount() > 0) {
this.extStore.each(function(r) {
if (r.data[prop] == value) {
record = r;
return false;
}
});
}
}
return record;
},
onClick: function(node) {
if (node.attributes.parameter == 9) {
//
} else {
//
this.setValue(node.text);
this.hiddenField.value = node.id;
this.collapse();
}
},
onExpand: function() {
this.tree.render(this.treeId);
}
});
Ext.reg("combotree", Ext.ux.ComboTree);
ComboTree.cs
Code:
[assembly: WebResource("Coolite.Ext.UX.Extensions.ComboTree.resources.ComboTree.js", "text/javascript")]
namespace Coolite.Ext.UX
{
[Designer(typeof(EmptyDesigner))]
[DefaultProperty("")]
[Xtype("combotree")]
[InstanceOf(ClassName = "Ext.ux.ComboTree")]
[ClientScript(Type = typeof(ComboTree), WebResource =
"Coolite.Ext.UX.Extensions.ComboTree.resources.ComboTree.js", FilePath
= "ux/extensions/combotree/combotree.js")]
[ToolboxData("<{0}:ComboTree runat=\"server\" Title=\"Combo tree\" Height=\"300\"></{0}:ComboTree>")]
[Description("Combobox with tree functionality")]
public class ComboTree : ComboBox
{
private TreeLoaderCollection treeLoader;
[ClientConfig("loader>Primary")]
[Category("Config Options")]
[NotifyParentProperty(true)]
[DefaultValue(null)]
[PersistenceMode(PersistenceMode.InnerProperty)]
[Description("The root node for the tree.")]
public virtual TreeLoaderCollection Loader
{
get
{
if (this.treeLoader == null)
{
this.treeLoader = new TreeLoaderCollection();
}
return this.treeLoader;
}
}
}
}
Usage:
Code:
<ux:ComboTree ID="_ct" runat="server">
<Loader>
<ext:PageTreeLoader OnNodeLoad="LoadTreeNodeEntries">
</ext:PageTreeLoader>
</Loader>
</ux:ComboTree>
I`m
trying to figure out whats the correct way to implement extensions by
the GMap extension, but i`m not sure if the code above is the right one
for my extension.
Can you pelase help me ?
Thx,
Peter
RE: Implementing a ComboTree extension
Hi,
I am not tested it but try the following
1. ComboTree.cs (don't forget required attributes for ComboTree class)
Code:
public class ComboTree : ComboBox
{
private ItemsCollection<TreePanel> tree;
[ClientConfig("tree", typeof(ItemCollectionJsonConverter))]
[Category("Config Options")]
[NotifyParentProperty(true)]
[DefaultValue(null)]
[PersistenceMode(PersistenceMode.InnerProperty)]
public virtual ItemsCollection<TreePanel> Tree
{
get
{
if (this.tree == null)
{
this.tree = new ItemsCollection<TreePanel>();
this.tree.SingleItemMode = true;
this.tree.AfterItemAdd += this.AfterItemAdd;
}
return this.tree;
}
}
protected virtual void AfterItemAdd(Component item)
{
this.Controls.Add(item);
if (!this.LazyItems.Contains(item))
{
this.LazyItems.Add(item);
}
}
}
2. ComboTree.js (initComponent.js function)
Code:
initComponent: function() {
this.treeId = Ext.id();
this.focusLinkId = Ext.id();
Ext.apply(this, {
store: new Ext.data.SimpleStore({
fields: [],
data: [[]]
}),
editable: false,
shadow: false,
mode: 'local',
triggerAction: 'all',
maxHeight: 200,
tpl: '<tpl for="."><div style="height:200px"><div id="'
+ this.treeId + '">
</tpl>',
selectedClass: '',
onSelect: Ext.emptyFn,
valueField: 'id'
});
this.tree = new Coolite.Ext.TreePanel(this.tree);
this.on('expand', this.onExpand);
this.tree.on('click', this.onClick, this);
Ext.ux.ComboTree.superclass.initComponent.apply(this, arguments);
}
3. Example
Code:
<%@ Page Language="C#" %>
<%@ Register Assembly="Coolite.Ext.Web" Namespace="Coolite.Ext.Web" TagPrefix="ext" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title></title>
<script runat="server">
protected void NodeLoad(object sender, NodeLoadEventArgs e)
{
if (!string.IsNullOrEmpty(e.NodeID))
{
for (int i = 1; i < 6; i++)
{
AsyncTreeNode asyncNode = new AsyncTreeNode();
asyncNode.Text = e.NodeID + i;
asyncNode.NodeID = e.NodeID + i;
e.Nodes.Add(asyncNode);
}
for (int i = 6; i < 11; i++)
{
Coolite.Ext.Web.TreeNode treeNode = new Coolite.Ext.Web.TreeNode();
treeNode.Text = e.NodeID + i;
treeNode.NodeID = e.NodeID + i;
treeNode.Leaf = true;
e.Nodes.Add(treeNode);
}
}
}
</script>
</head>
<body>
<form id="form1" runat="server">
<ext:ScriptManager ID="ScriptManager1" runat="server" />
<ext:ComboTree ID="_ct" runat="server">
<Tree>
<ext:TreePanel
ID="TreePanel1"
runat="server"
Title="Tree"
AutoHeight="true"
Border="false">
<Loader>
<ext:PageTreeLoader OnNodeLoad="NodeLoad">
</ext:PageTreeLoader>
</Loader>
<Root>
<ext:AsyncTreeNode NodeID="0" Text="Root" />
</Root>
</ext:TreePanel>
</Tree>
</ext:ComboTree>
</form>
</body>
</html>
RE: Implementing a ComboTree extension
Hi Vlad,
thanks for your reply.
The problem with the solution you provided is, that the AfterItemAdd event and the SingleItemMode property of the ItemCollection can be accessed internally only. So I would need to move the control to the Coolite core package.
But I would like to keep it in the plugin package because I think it`s a far cleaner approach.
Do you have any ideas or workarounds ?
Thx,
Peter
RE: Implementing a ComboTree extension
Hi,
Well, you can skip SingleItemMode (just be sure that you use single tree or check it manually, for example on LoadComplete event)
I think AfterItemAdd can be skiped also. Just add tree to the Controls collection on OnLoad function (override it)
Code:
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
}
RE: Implementing a ComboTree extension
Thanks vlad, that`s it !
For anyone who has the same problem, do not forget to add the tree to the LazyItems-Collection too !!
Code:
protected override void OnLoad(EventArgs e)
{
this.Controls.Add(Tree[0]);
if (!this.LazyItems.Contains(Tree[0]))
{
this.LazyItems.Add(Tree[0]);
}
base.OnLoad(e);
}
RE: Implementing a ComboTree extension
Quote:
pschojer (6/29/2009)Hi guys,
as i`ve already posted
here I need a ComboTree component for my application.
I am now trying to implement the extension on myself within the Ext.UX project.
I`ve compiled my customized extension library successfully and the control is showing up in my application.
However, when i expand a node within the tree popup the assigned TreeLoader event is never raised server-side.
A request to the server is made, but it fails with an error message ("control ext-gen1000 not found").
Here is my code:
ComboTree.js
Code:
Ext.namespace('Ext.ux');
/**
*
* @class ComboTree
* @extends Ext.form.ComboBox
*/
Ext.ux.ComboTree = Ext.extend(Ext.form.ComboBox, {
extStore: null,
tree: null,
treeId: 0,
setValue: function(v) {
var text = v;
if (this.valueField) {
var r = this.findExtRecord(this.valueField, v);
if (r) {
text = r.data[this.displayField];
} else if (this.valueNotFoundText !== undefined) {
text = this.valueNotFoundText;
}
}
Ext.ux.ComboTree.superclass.setValue.call(this, text);
this.lastSelectionText = text;
if (this.hiddenField) {
this.hiddenField.value = v;
}
this.value = v;
},
initComponent: function() {
this.treeId = Ext.id();
this.focusLinkId = Ext.id();
Ext.apply(this, {
store: new Ext.data.SimpleStore({
fields: [],
data: [[]]
}),
editable: false,
shadow: false,
mode: 'local',
triggerAction: 'all',
maxHeight: 200,
tpl: '<tpl for="."><div style="height:200px"><div id="'
+ this.treeId + '">
</tpl>',
selectedClass: '',
onSelect: Ext.emptyFn,
valueField: 'id'
});
var treeConfig = {
border: false,
rootVisible: true,
loader: this.loader // loader is assigned here
};
Ext.apply(treeConfig, this.treeConfig);
if (!treeConfig.root) {
treeConfig.root = new Ext.tree.AsyncTreeNode({
text: 'treeRoot',
id: '0'
});
}
this.tree = new Ext.tree.TreePanel(treeConfig);
this.on('expand', this.onExpand);
this.tree.on('click', this.onClick, this);
Ext.ux.ComboTree.superclass.initComponent.apply(this,
arguments);
},
findExtRecord: function(prop, value) {
var record;
if (this.extStore != null) {
if (this.extStore.getCount() > 0) {
this.extStore.each(function(r) {
if (r.data[prop] == value) {
record = r;
return false;
}
});
}
}
return record;
},
onClick: function(node) {
if (node.attributes.parameter == 9) {
//
} else {
//
this.setValue(node.text);
this.hiddenField.value = node.id;
this.collapse();
}
},
onExpand: function() {
this.tree.render(this.treeId);
}
});
Ext.reg("combotree", Ext.ux.ComboTree);
ComboTree.cs
Code:
[assembly: WebResource("Coolite.Ext.UX.Extensions.ComboTree.resources.ComboTree.js", "text/javascript")]
namespace Coolite.Ext.UX
{
[Designer(typeof(EmptyDesigner))]
[DefaultProperty("")]
[Xtype("combotree")]
[InstanceOf(ClassName = "Ext.ux.ComboTree")]
[ClientScript(Type = typeof(ComboTree), WebResource =
"Coolite.Ext.UX.Extensions.ComboTree.resources.ComboTree.js", FilePath
= "ux/extensions/combotree/combotree.js")]
[ToolboxData("<{0}:ComboTree runat=\"server\" Title=\"Combo tree\" Height=\"300\"></{0}:ComboTree>")]
[Description("Combobox with tree functionality")]
public class ComboTree : ComboBox
{
private TreeLoaderCollection treeLoader;
[ClientConfig("loader>Primary")]
[Category("Config Options")]
[NotifyParentProperty(true)]
[DefaultValue(null)]
[PersistenceMode(PersistenceMode.InnerProperty)]
[Description("The root node for the tree.")]
public virtual TreeLoaderCollection Loader
{
get
{
if (this.treeLoader == null)
{
this.treeLoader = new TreeLoaderCollection();
}
return this.treeLoader;
}
}
}
}
Usage:
Code:
<ux:ComboTree ID="_ct" runat="server">
<Loader>
<ext:PageTreeLoader OnNodeLoad="LoadTreeNodeEntries">
</ext:PageTreeLoader>
</Loader>
</ux:ComboTree>
I`m
trying to figure out whats the correct way to implement extensions by
the GMap extension, but i`m not sure if the code above is the right one
for my extension.
Can you pelase help me ?
Thx,
Peter
Hi,pschojer
do you shaing your component?
that it's very cool .
RE: Implementing a ComboTree extension
Ok, here is the final source (attached also!).
ComboTree.js:
Code:
Ext.namespace('Ext.ux');
/**
*
* @class ComboTree
* @extends Ext.form.ComboBox
*/
Ext.ux.ComboTree = Ext.extend(Ext.form.ComboBox, {
extStore: null,
tree: null,
treeId: 0,
setValue: function(v) {
var text = v;
if (this.valueField) {
var r = this.findExtRecord(this.valueField, v);
if (r) {
text = r.data[this.displayField];
} else if (this.valueNotFoundText !== undefined) {
text = this.valueNotFoundText;
}
}
Ext.ux.ComboTree.superclass.setValue.call(this, text);
this.lastSelectionText = text;
if (this.hiddenField) {
this.hiddenField.value = v;
}
this.value = v;
},
initComponent: function() {
this.treeId = Ext.id();
this.focusLinkId = Ext.id();
Ext.apply(this, {
store: new Ext.data.SimpleStore({
fields: [],
data: [[]]
}),
editable: false,
shadow: false,
mode: 'local',
triggerAction: 'all',
maxHeight: 200,
tpl: '<tpl for="."><div style="height:200px"><div id="'
+ this.treeId + '">
</tpl>',
selectedClass: '',
onSelect: Ext.emptyFn,
valueField: 'id'
});
this.tree = new Coolite.Ext.TreePanel(this.tree);
this.on('expand', this.onExpand);
this.tree.on('click', this.onClick, this);
Ext.ux.ComboTree.superclass.initComponent.apply(this, arguments);
},
findExtRecord: function(prop, value) {
var record;
if (this.extStore != null) {
if (this.extStore.getCount() > 0) {
this.extStore.each(function(r) {
if (r.data[prop] == value) {
record = r;
return false;
}
});
}
}
return record;
},
onClick: function(node) {
if (node.attributes.parameter == 9) {
//
} else {
//
this.setValue(node.text);
this.hiddenField.value = node.id;
this.collapse();
}
},
onExpand: function() {
this.tree.render(this.treeId);
}
});
Ext.reg("combotree", Ext.ux.ComboTree);
ComboTree.cs
Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Web.UI;
using Coolite.Ext.Web;
[assembly: WebResource("Coolite.Ext.UX.Extensions.ComboTree.resources.ComboTree.js", "text/javascript")]
namespace Coolite.Ext.UX
{
[Designer(typeof(EmptyDesigner))]
[DefaultProperty("")]
[Xtype("combotree")]
[InstanceOf(ClassName = "Ext.ux.ComboTree")]
[ClientScript(Type = typeof(ComboTree), WebResource = "Coolite.Ext.UX.Extensions.ComboTree.resources.ComboTree.js", FilePath = "ux/extensions/combotree/combotree.js")]
[ToolboxData("<{0}:ComboTree runat=\"server\" Title=\"Combo tree\" Height=\"300\"></{0}:ComboTree>")]
[Description("Combobox with tree functionality")]
public class ComboTree : ComboBox
{
private ItemsCollection<TreePanel> tree;
[ClientConfig("tree", typeof(ItemCollectionJsonConverter))]
[Category("Config Options")]
[NotifyParentProperty(true)]
[DefaultValue(null)]
[PersistenceMode(PersistenceMode.InnerProperty)]
public virtual ItemsCollection<TreePanel> Tree
{
get
{
if (this.tree == null)
{
this.tree = new ItemsCollection<TreePanel>();
}
return this.tree;
}
}
protected override void OnLoad(EventArgs e)
{
this.Controls.Add(Tree[0]);
if (!this.LazyItems.Contains(Tree[0]))
{
this.LazyItems.Add(Tree[0]);
}
base.OnLoad(e);
}
}
}
Thanks also to the original coder of the ExtJS extension neo_sun !
Peter
RE: Implementing a ComboTree extension
very thx.
But i use that add into Coolite.ux project and generate to dll,adding ux to toolbox,and usage
can not find like this:
Code:
<Loader>
<ext:PageTreeLoader OnNodeLoad="LoadTreeNodeEntries">
</ext:PageTreeLoader>
</Loader>
that like this:
Code:
<ux:ComboTree ID="ComboTree1" runat="server" Height="300" Title="Combo tree">
<Tree>
<ext:TreePanel ></ext:TreePanel>
</Tree>
</ux:ComboTree>
when i run my page ,can't see anymore in my page,it's none.
how to use that?
RE: Implementing a ComboTree extension
Hi can you so usage.
Because when I run it I get js error object required.
here is how I used it
html
Code:
<ux:ComboTree ID="ComboTree1" runat="server" Height="400" Title="Combo tree" >
<Tree>
<ext:TreePanel ID="Tree" runat="server" Height="300" AutoHeight="true">
<Root>
<ext:AsyncTreeNode NodeID="0" Text="Root" />
</Root>
<Listeners>
<BeforeLoad Fn="nodeLoad" />
</Listeners>
</ext:TreePanel>
</Tree>
</ux:ComboTree>
js
Code:
function nodeLoad(node) {
Coolite.AjaxMethods.NodeLoad(node.id, {
success: function(result) {
var data = eval("(" + result + ")");
node.loadNodes(data);
},
failure: function(errorMsg) {
Ext.Msg.alert('Failure', errorMsg);
}
});
}
Vb
Code:
<Coolite.Ext.Web.AjaxMethod()> _
Public Function NodeLoad(ByVal sender As Object, ByVal e As Coolite.Ext.Web.NodeLoadEventArgs) As String
Dim nodes As Coolite.Ext.Web.TreeNodeCollection = New Coolite.Ext.Web.TreeNodeCollection()
Dim dr As MySqlDataReader
Dim getInfo As New general
dr = getInfo.coolMY("select * from structure where parentid = 0", Session.Item("strcon"))
While dr.Read
Dim asyncNode As Coolite.Ext.Web.AsyncTreeNode = New Coolite.Ext.Web.AsyncTreeNode()
asyncNode.Text = dr(2)
asyncNode.NodeID = dr(1)
nodes.Add(asyncNode)
End While
Return nodes.ToJson()
End Function
RE: Implementing a ComboTree extension
Moving to USER EXTENSIONS AND PLUGINS forum.