Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Programmatically tab to next control in Ext JS

I've written a wrapper UX control in Ext JS 2.x around Ext.Form.DateField to handle keypresses slightly differently. In particular, when the calendar is on display, I want the Tab key to select the highlighted date and move to the next form field.

I've got the key handler working – it selects the highlighted date and closes the calendar – but I can't get it to tab to the next field.

Do I have to work out what the next field is from the tab order and try to set its focus? That seems rather convoluted. Or can I fire some event to get my control to tab to the next field automatically (i.e. capture the Tab keypress in the calendar and process it, as I am doing, but then forward it to the underlying date field)?


Edit: In summary, is there an Ext (or, at least cross-platform) way to fire a keyboard event at a particular form field?

like image 373
Matthew Strawbridge Avatar asked Oct 21 '12 09:10

Matthew Strawbridge


1 Answers

Approach I. Just don't do event.preventDefault() in your keypress/keyup event handler so you don't block the browser from performing the default action, i.e. tab-navigation. This example works:

Ext.create('Ext.form.Panel', {
    title: 'Contact Info',
    width: 300,
    renderTo: Ext.getBody(),
    items: [{
        xtype: 'textfield',
        name: 'name',
        fieldLabel: 'Name',
        listeners: {
            specialkey: function(me, e) {
                if (e.getKey() == e.TAB) {
                        console.log('Tab key pressed!');
                        // do whatever you want here just don't do e.preventDefault() or e.stopEvent() if you want the browser tab to next control
                    }
            }
        }
    }, {
        xtype: 'textfield',
        name: 'email',
        fieldLabel: 'Email Address',
    }]
});

I tried it in Ext 4 but all the essential methods should be available since Ext 2. If you still experience issues please share some of your code.

Getting out of the way and letting the browser do its stuff natively is usually the best and the most robust solution...


Approach II. If you have a complicated component with multiple elements, you can still achieve the case of Approach I. by forcing the focus on the main input element (usually a text field) while simulating focusing items inside a popup element with CSS (a KeyNav/KeyMap in the main input element would be handy here). You just basically catch all the cases where the user may set the focus on a popup (like clicking on it) and snap the focus back to your main element.

This would still ensure the natural tab order of html elements, even if some of them are not Components. I believe that's the best way to go and worth struggling to achieve most of the time.

That's the way components like ComboBox and DatePicker work (as you can see the latter just always sets focus to the main element after the vaule is updated. The focus logic of a ComboBox is a bit more complicated. Take a look at the source code links if you're confused about how to implement it in your component, very insightful.


Approach III. Last resort. If you still need to just programmatically focus another (neighbour) field, that's relatively easy to do. Code for Ext 2.3 (didn't test it though, I was using the docs):

var formPanel,  // containing form panel
    currentField, // the field you need to navigate away from

    fields,
    currentFieldIdx,
    nextField;

fields = formPanel.getForm().items;
currentFieldIdx = fields.indexOf(currentField);

if(currentFieldIdx > -1) {
    nextField = fields.itemAt(currentFieldIdx + 1);
    nextField && nextField.focus();
}

P.S. You can artificially fire the Tab key press via dispatchEvent() but it will not trigger the tab-navigation action due to security reasons.

like image 142
Dmitry Pashkevich Avatar answered Sep 22 '22 06:09

Dmitry Pashkevich