PDA

View Full Version : ComboBox getValue problem on Enter key press



aluxner
12 Sep 2013, 4:31 PM
There seems to a be a bug in the combo box behavior when the user types in the combo box and presses the keyboard Enter key. I didn't post this in the bugs forum because I'm new to Ext JS and thought there might be a work-around that someone could share. The goal is to programmatically have the Enter key press have the same behavior as when the user clicks the Save button using the mouse. In this example the event handler on the Enter button indeed causes the ComboBox’s blur event to trigger (the blur event handler will print out a message verifying this), the focus moves to the button, and the button is programmatically clicked, causing the reportForm function to execute. So I am able to programmatically click the Save button.

The problem is that the value that the user has typed is not set in the combo box and is not retrieved via the getValue method until after the user has changed focus. The function's output will confirm this. This is not acceptable because the form values are required at the enter-key press, as the form is about to submit. Here is a test case to demonstrate, followed by the code needed to run the test:

Test of Ext JS 3.4 combobox behavior

Setup

From a clean form (refresh browser if necessary) type a value in the text field (the 2nd form field). Then type a vlaue in the combo box. Do not tab out of the combo box. Leave the cursor there.
Scenario 1

Follow Setup step above. Then use your mouse to click the Save button. A javascript function assigned to the button prints the "raw" value of the combo box (combobox.getRawValue()), the value of the combo box (combobox.getValue()) and the value of the text field. Note that the values print out as expected and the raw and regular combo box values match.
Scenario 2

Follow Setup step above. Then click your keyboard's Enter key. The same javascript function described in scenario 1 has been registered to run when the Enter key is pressed. I expect the exact same behavior as in Scenario 1 but unfortunately in this case while the RAW value of the combo box is as expected (it is whatever you typed in the field) the combobox.getValue() is blank (or the previously-typed value if you didn't refresh the browser).

Finally, here is the code:


<html>
<head>
<title>Test of Ext JS 3.4 Combo behavior</title>
<link rel="stylesheet" type="text/css"
href="extjs/resources/css/ext-all.css" />
<script type="text/javascript" src="extjs/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="extjs/ext-all-debug.js"></script>
<script type="text/javascript">
Ext.onReady(function() { new Ext.Viewport({
items: [myForm],
applyTo: 'formContent'
});
});

function reportForm(){
var combo = Ext.getCmp('ajlCombo');
var rawComboVal = combo.getRawValue();
console.log('RAW value of combo box:' + rawComboVal);
//combo.setValue(rawComboVal);
// Uncommenting the above line almost has the desired effect but the combo
// value will not be validated

// if things work as desired the combo value will contain what the user typed
// in the field, even if focus is still in the field.
var comboVal = combo.getValue();
console.log('Value of combo box:' + comboVal);

var tf = Ext.getCmp('ajlTextField');
var tfVal = tf.getValue();
console.log('Value of text field:' + tfVal);
var formPanel = Ext.getCmp('ajlForm');
var form = formPanel.getForm();
}
var dataArr = ['alpha','bravo','charlie','delta'];


var myForm = new Ext.FormPanel({
labelWidth : 75,
standardSubmit: true,
frame : true,
title : 'Test Form',
id : 'ajlForm',
bodyStyle : 'padding:5px 5px 0',
width : 350,
defaults : {
width : 230
},
items : [{
xtype : 'combo',
id : 'ajlCombo',
enableKeyEvents: true,
listeners:{
blur: function() {
console.log('ajlCombo has blurred');
}
},
store : dataArr
}, {
xtype : 'textfield',
id : 'ajlTextField'
}],


buttons : [{
text : 'Save',
id : 'ajlButton',
handler : reportForm
}],
keys: {
key: Ext.EventObject.ENTER,
scope:this,
// cause reportForm function to be invoked when Enter button pressed
fn: function(){
// try to programmatically cause the button click
var combo = Ext.getCmp('ajlCombo');
var comboElement = combo.getEl();
comboElement.blur();
var enterBtn = Ext.getCmp('ajlButton');
var btnElement = enterBtn.getEl();
btnElement.focus();
btnElement.dom.click.defer(100, btnElement.dom);
}
}
});
</script>
</head>
<body></body>
</html>

Thanks in advance to anyone who can offer advice on getting the user-entered combo box value to be set in the combo-box as the Enter key has pressed, without an ugly work-around such as using the getRawValue() method. Evidence will be that following either scenario above will cause the same values to be printed out.

willigogs
13 Sep 2013, 12:37 AM
In your above example, could you not run the form's "isValid" method after updating the value from the rawValue? Then the field would be validated :)

http://docs.sencha.com/extjs/3.4.0/#!/api/Ext.form.BasicForm-method-isValid

aluxner
13 Sep 2013, 4:06 PM
Thanks for your response. I've updated the code and the explanation for more clarity. What you suggest will work but I really don't want to have to do that kind of a work-around. The hope was that there would be a way to more faithfully simulate the click of a button so there would be no need to manipulate the ComboBox values.

willigogs
16 Sep 2013, 1:10 AM
What type of validation are you running against the combo on clicking enter?

I'll try creating a quick example and see what I find :)

aluxner
16 Sep 2013, 8:40 AM
Thanks again for your help. The validation I do varies, but for example I might validate the field for a minimum or maximum number of characters.

slemmon
16 Sep 2013, 9:14 AM
I used the specialkey (http://docs.sencha.com/extjs/4.2.1/#!/api/Ext.form.field.ComboBox-event-specialkey) event handler and that seemed to work ok for me.

See test case below:

https://fiddle.sencha.com/#fiddle/if



Ext.onReady(function() {
function reportForm() {
var combo = Ext.getCmp('ajlCombo');
var rawComboVal = combo.getRawValue();
console.log('RAW value of combo box:' + rawComboVal);
//combo.setValue(rawComboVal);
// Uncommenting the above line almost has the desired effect but the combo
// value will not be validated


// if things work as desired the combo value will contain what the user typed
// in the field, even if focus is still in the field.
var comboVal = combo.getValue();
console.log('Value of combo box:' + comboVal);


var tf = Ext.getCmp('ajlTextField');
var tfVal = tf.getValue();
console.log('Value of text field:' + tfVal);
var formPanel = Ext.getCmp('ajlForm');
var form = formPanel.getForm();
}
var dataArr = ['alpha', 'bravo', 'charlie', 'delta'];




var myForm = new Ext.FormPanel({
labelWidth: 75,
standardSubmit: true,
frame: true,
title: 'Test Form',
id: 'ajlForm',
bodyStyle: 'padding:5px 5px 0',
width: 350,
defaults: {
width: 230
},
items: [{
xtype: 'combo',
id: 'ajlCombo',
enableKeyEvents: true,
listeners: {
blur: function() {
console.log('ajlCombo has blurred');
},
specialkey: function(field, e) {
if (e.getKey() == e.ENTER) {
reportForm();
}
}
},
store: dataArr
}, {
xtype: 'textfield',
id: 'ajlTextField'
}],




buttons: [{
text: 'Save',
id: 'ajlButton',
handler: reportForm
}],
/*keys: {
key: Ext.EventObject.ENTER,
scope:this,
// cause reportForm function to be invoked when Enter button pressed
fn: function(){
// try to programmatically cause the button click
var combo = Ext.getCmp('ajlCombo');
var comboElement = combo.getEl();
comboElement.blur();
var enterBtn = Ext.getCmp('ajlButton');
var btnElement = enterBtn.getEl();
btnElement.focus();
btnElement.dom.click.defer(100, btnElement.dom);
}
}*/
});




new Ext.Viewport({
items: [myForm] //,
//applyTo: 'formContent'
});
});

willigogs
16 Sep 2013, 9:27 AM
Thanks again for your help. The validation I do varies, but for example I might validate the field for a minimum or maximum number of characters.
In the test I did, I set validation parameters of allowBlank, minLength and maxLength, then hooked into the keyup event of the combo. Upon detecting keyup of the Enter key, I simply ran form.getForm().isValid(), and it validated the form as anticipated.

e.g:
http://jsfiddle.net/Whinters/GMwuD/

aluxner
16 Sep 2013, 12:23 PM
Thanks for your reply. I found that using a specialkey handler on the ComboBox works the same as the "keys" handler you commented out. You could put that commented out code in the specialkey handler and things would work the same. The goal is have the enter key cause a click of the "ajlButton". In your code you're just directly calling reportForm, which is fine - reportForm will run when Enter is pressed - but the problem remains: If you follow scenario 2 above and type in the text field, leaving focus there, and then click the Enter key, the combo-box's value will not have been updated, so if you're submitting the form the ComboBox value will be lost unless you code a work-around.

slemmon
16 Sep 2013, 1:18 PM
Ok. I think I'm with you now. Not sure why the difference.

How about:


specialkey: function (field, e) {
if (e.getKey() == e.ENTER) {
field.setValue(field.getRawValue());
reportForm();
}
}

aluxner
20 Sep 2013, 3:26 PM
Hi again,
I saw your code. Yes, I'd experimented with the isValid() before and it's useful for some cases. But, with an Enter key press, even after calling isValid the ComboBox value is not updated, regardless of the result. I updated your example to print out the value of a button click vs. a key press. That jsfiddle is pretty cool by the way. Ok, the validation will work, and getRawValue can be used to get the real value in the case that validation passes. I still don't like the solution because this is not just a one-time hack, this solution is part of a component that will be reused many times. I'm still hoping there's a better way to simulate the button click behavior.