PDA

View Full Version : [CLOSED] Combo selected text



Adrian
Jan 23, 2012, 6:47 AM
Hi
How do I get the text (via a direct event) entered in a combobox when ForceSelection = false and the user enters a value which is NOT in the list of items? In Ext.Net 2.0 .SelectedIem.Text currently throws an error (Object reference not set to an instance of an object).

Thanks.

Daniil
Jan 23, 2012, 9:39 AM
Hi,

Thanks for the report.

There is no way to get it in DP1 apart from a DirectEvent's extra parameter, a text is not automatically submitted from client.

We will fix it.

For now, I'm not sure it will be the same as it's in v1, i.e. getting that text from SelectedItem.Text, because it's not really a selected item, so, not logical.

We will fix and update the thread.

Adrian
Jan 23, 2012, 10:35 AM
Thanks Daniil
Could you tell me if the fix will be available via SVN in a reasonable timeframe or will we have to wait until DP2 - which I assume is dependant on ExtJs4.1 (scheduled for late March)?

I have a lot of comboboxes which accept both selected items and custom text so in order to continue building in Ext 2.0 I need to be able to both get and set custom text.

Thanks,
Adrian.

geoffrey.mcgill
Jan 23, 2012, 4:55 PM
Thanks Daniil
Could you tell me if the fix will be available via SVN in a reasonable timeframe or will we have to wait until DP2 - which I assume is dependant on ExtJs4.1 (scheduled for late March)?

I have a lot of comboboxes which accept both selected items and custom text so in order to continue building in Ext 2.0 I need to be able to both get and set custom text.

Thanks,
Adrian.

We are fixing, and will post the source-code changes here. This will enable you to just patch your local Ext.NET source files and recompile.

The official fix will be included in the next Ext.NET v2 release, which will include Ext JS 4.1 Beta 2.

Adrian
Jan 23, 2012, 9:22 PM
That's great. Thank you.

A.

Daniil
Jan 25, 2012, 12:09 PM
The fix has been added to SVN.

Here is the new code of LoadPostData in ComboBoxBase.cs .

Fix (Ext.Net\Ext\Form\ComboBoxBase.cs)

protected override bool LoadPostData(string postDataKey, NameValueCollection postCollection)
{
this.HasLoadPostData = true;

string text = postCollection[this.UniqueName];
string state = postCollection["_" + this.UniqueName + "_state"];

this.SuspendScripting();
this.RawValue = text;
this.Value = text;
this.ResumeScripting();

if (state == null && text == null)
{
return false;
}

if (!this.EmptyText.Equals(text) && text.IsNotEmpty())
{
List<ListItem> items = null;
if (this.SimpleSubmit)
{
var array = state.Split(new char[] { ',' });
items = new List<ListItem>(array.Length);
foreach (var item in array)
{
items.Add(new ListItem(item));
}
}
else if(state.IsNotEmpty())
{
items = ComboBoxBase.ParseSelectedItems(state);
}

bool fireEvent = false;

if (items == null)
{
items = new List<ListItem>
{
new ListItem(text)
};

/*fireEvent = this.SelectedItems.Count > 0;
this.SelectedItems.Clear();
return fireEvent;
*/
}

foreach (var item in items)
{
if (!this.SelectedItems.Contains(item))
{
fireEvent = true;
break;
}
}

this.SelectedItems.Clear();
this.SelectedItems.AddRange(items);

return fireEvent;
}
else
{
if (this.EmptyText.Equals(text) && this.SelectedItems.Count > 0)
{
this.SelectedItems.Clear();

return true;
}
}

return false;
}

Adrian
Jan 30, 2012, 1:21 AM
Thanks for the updated code Daniil.

So that we get the new approach correct, could you please provide an example - based on Ext.Net 2.0 - using DirectEvents, for:

1. Assigning values to a combobox (when forceselection = false) and the value could be either present, or not present, in the list of items i.e. what approach should be taken now instead of combobox1.SelectedItem.Text = "Some Value".

2. Reading values from a combobox when items are both present in the list and not present.

Appreciate your assistance,
Adrian.

Daniil
Jan 30, 2012, 11:29 AM
Hi,

Here you are.

Example

<%@ Page Language="C#" %>

<%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>

<script runat="server">
protected void GetValue(object sender, DirectEventArgs e)
{
string v = this.ComboBox1.SelectedItem.Value;
string t = this.ComboBox1.SelectedItem.Text;
string msg = string.Format("Text: {0}<br/>Value: {1}", t, v);
X.Msg.Alert("ComboBox", msg).Show();
}

protected void SetItem(object sender, DirectEventArgs e)
{
this.ComboBox1.Value = "2";

//or

//this.ComboBox1.Text = "2";

//or

//this.ComboBox1.SetValue("2");
}

protected void SetText(object sender, DirectEventArgs e)
{
this.ComboBox1.Value = "Hello World!";

//or

//this.ComboBox1.Text = "Hello World!";

//or

//this.ComboBox1.SetValue("Hello World!");
}
</script>

<!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 runat="server">
<title>Ext.NET v2 Example</title>
</head>
<body>
<form runat="server">
<ext:ResourceManager runat="server" />
<ext:ComboBox ID="ComboBox1" runat="server" LazyMode="Instance">
<Items>
<ext:ListItem Text="Item 1" Value="1" />
<ext:ListItem Text="Item 2" Value="2" />
</Items>
<SelectedItems>
<ext:ListItem Index="0" />
</SelectedItems>
</ext:ComboBox>
<ext:Button runat="server" Text="Get value" OnDirectClick="GetValue" />
<ext:Button runat="server" Text="Set item" OnDirectClick="SetItem" />
<ext:Button runat="server" Text="Set text" OnDirectClick="SetText" />
</form>
</body>
</html>

Adrian
Jan 30, 2012, 10:43 PM
Thanks Daniil. Much appreciated.

A.

Adrian
Jan 30, 2012, 11:29 PM
Hi Daniil,
Using your example it is still the case that if you type a custom entry which is not in the list of items both ComboBox1.SelectedItem.Text and ComboBox1.Text (or ComboBox1.Value) fail to retrieve the correct text/value - the text/value will default to the previous selected list item.

Also, if a combo box is not assigned a pre-selected value (ie it is left blank) and the user does not select a listed item, but rather enters a custom value, you will get an 'Object reference not set to an instance of an object' error on a direct event.

Thanks for your ongoing help.
Adrian.

Daniil
Jan 31, 2012, 8:23 AM
Using your example it is still the case that if you type a custom entry which is not in the list of items both ComboBox1.SelectedItem.Text and ComboBox1.Text (or ComboBox1.Value) fail to retrieve the correct text/value - the text/value will default to the previous selected list item.


Please clarify did you apply the fix and rebuild the Ext.NET sources?



Also, if a combo box is not assigned a pre-selected value (ie it is left blank) and the user does not select a listed item, but rather enters a custom value, you will get an 'Object reference not set to an instance of an object' error on a direct event.


Confirmed. We are looking into it.

Please check a SelectedItem on null.

Adrian
Jan 31, 2012, 8:49 AM
Yes, I can confirm we've applied the fix to LoadPostData in ComboBoxBase.cs and rebuilt Ext.Net sources.

A.

Daniil
Jan 31, 2012, 1:15 PM
I can confirm we've applied the fix to LoadPostData in ComboBoxBase.cs and rebuilt Ext.Net sources.

Confirmed. LoadPostData is not enough. The fix is related to more files.

Please add the following thing into a page's <head>. This doesn't require rebuilding the Ext.NET sources.

Fix

<ext:ResourcePlaceHolder runat="server" Mode="ScriptFiles" />

<script type="text/javascript">
Ext.form.field.ComboBox.override({
hiddenName : "",

fieldSubTpl: [
'<div class="{hiddenDataCls}" role="presentation"></div>',
'<input id="{id}" type="{type}" ',
'<tpl if="size">size="{size}" </tpl>',
'<tpl if="tabIdx">tabIndex="{tabIdx}" </tpl>',
'<tpl if="name">name="{name}"</tpl>',

'class="{fieldCls} {typeCls}" autocomplete="off" />',
'<div id="{cmpId}-triggerWrap" class="{triggerWrapCls}" role="presentation">',
'{triggerEl}',
'<div class="{clearCls}" role="presentation"></div>',
'</div>',
{
compiled: true,
disableFormats: true
}
],

setHiddenValue: function(values){
var me = this,
name = me.hiddenName,
i;

if (!me.hiddenDataEl || !name) {
return;
}
values = Ext.Array.from(values);
var dom = me.hiddenDataEl.dom,
childNodes = dom.childNodes,
input = childNodes[0],
valueCount = values.length,
childrenCount = childNodes.length;

if (!input && valueCount > 0) {
me.hiddenDataEl.update(Ext.DomHelper.markup({
tag: 'input',
type: 'hidden',
name: name
}));
childrenCount = 1;
input = dom.firstChild;
}
while (childrenCount > valueCount) {
dom.removeChild(childNodes[0]);
-- childrenCount;
}
while (childrenCount < valueCount) {
dom.appendChild(input.cloneNode(true));
++ childrenCount;
}
for (i = 0; i < valueCount; i++) {
childNodes[i].value = values[i];
}
}
});
</script>

Here is the full example.

Example

<%@ Page Language="C#" %>

<%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>

<script runat="server">
protected void GetValue(object sender, DirectEventArgs e)
{
string msg;

if (this.ComboBox1.SelectedItem != null)
{
string v = this.ComboBox1.SelectedItem.Value;
string t = this.ComboBox1.SelectedItem.Text;
msg = string.Format("Text: {0}<br/>Value: {1}", t, v);
}
else
{
msg = "The ComboBox is empty.";
}
X.Msg.Alert("ComboBox", msg).Show();
}

protected void SetItem(object sender, DirectEventArgs e)
{
this.ComboBox1.Value = "2";

//or

//this.ComboBox1.Text = "2";

//or

//this.ComboBox1.SetValue("2");
}

protected void SetText(object sender, DirectEventArgs e)
{
this.ComboBox1.Value = "Hello World!";

//or

//this.ComboBox1.Text = "Hello World!";

//or

//this.ComboBox1.SetValue("Hello World!");
}
</script>

<!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 runat="server">
<title>Ext.NET v2 Example</title>

<ext:ResourcePlaceHolder runat="server" Mode="ScriptFiles" />

<script type="text/javascript">
Ext.form.field.ComboBox.override({
hiddenName : "",

fieldSubTpl: [
'<div class="{hiddenDataCls}" role="presentation"></div>',
'<input id="{id}" type="{type}" ',
'<tpl if="size">size="{size}" </tpl>',
'<tpl if="tabIdx">tabIndex="{tabIdx}" </tpl>',
'<tpl if="name">name="{name}"</tpl>',

'class="{fieldCls} {typeCls}" autocomplete="off" />',
'<div id="{cmpId}-triggerWrap" class="{triggerWrapCls}" role="presentation">',
'{triggerEl}',
'<div class="{clearCls}" role="presentation"></div>',
'</div>',
{
compiled: true,
disableFormats: true
}
],

setHiddenValue: function(values){
var me = this,
name = me.hiddenName,
i;

if (!me.hiddenDataEl || !name) {
return;
}
values = Ext.Array.from(values);
var dom = me.hiddenDataEl.dom,
childNodes = dom.childNodes,
input = childNodes[0],
valueCount = values.length,
childrenCount = childNodes.length;

if (!input && valueCount > 0) {
me.hiddenDataEl.update(Ext.DomHelper.markup({
tag: 'input',
type: 'hidden',
name: name
}));
childrenCount = 1;
input = dom.firstChild;
}
while (childrenCount > valueCount) {
dom.removeChild(childNodes[0]);
-- childrenCount;
}
while (childrenCount < valueCount) {
dom.appendChild(input.cloneNode(true));
++ childrenCount;
}
for (i = 0; i < valueCount; i++) {
childNodes[i].value = values[i];
}
}
});
</script>
</head>
<body>
<form runat="server">
<ext:ResourceManager runat="server" />
<ext:ComboBox ID="ComboBox1" runat="server" LazyMode="Instance">
<Items>
<ext:ListItem Text="Item 1" Value="1" />
<ext:ListItem Text="Item 2" Value="2" />
</Items>
<SelectedItems>
<ext:ListItem Index="0" />
</SelectedItems>
</ext:ComboBox>
<ext:Button runat="server" Text="Get value" OnDirectClick="GetValue" />
<ext:Button runat="server" Text="Set item" OnDirectClick="SetItem" />
<ext:Button runat="server" Text="Set text" OnDirectClick="SetText" />
</form>
</body>
</html>

Adrian
Feb 01, 2012, 12:47 AM
I can confirm the code above fixes the issue for DP1.
Thanks guys. Appreciate the rapid response.

Adrian.