Make ExtJS input field lose focus - extjs

I have a numberfield input which I want to lose focus when the user hits the enter key.
Here's the current config:
{
xtype: 'numberfield',
minValue: 0,
maxValue: 99999,
hideTrigger: true,
keyNavEnabled: false,
mouseWheelEnabled: false,
enableKeyEvents: true,
listeners: {
specialkey: function(f, e) {
if (e.getKey() == e.ENTER)
f.blur();
}
}
}
The specialkey handler works, calling blur() as expected, but the only result is that the caret disappears from the input (indicating that the DOM text input element has been blurred). The field still has all the x-form-focus etc css classes, and examining the object shows that the private hasFocus property is still true.
Any suggestions?
I have tried calling f.onBlur() explicitly after the blur() call, but it made no difference.
(btw the field does not belong to a form so there is no form to submit.)

The fix. The issue is caused by a weird behavior in the Ext.form.field.Trigger class where they don't trigger 'triggerBlur()' when the regular 'blur()' function is called. Very interesting:
listeners: {
specialkey: function(f, e) {
if (e.getKey() == e.ENTER)
{
f.triggerBlur();
f.blur();
}
}
}

This works for me :
specialkey: function(field,events) {
if (events.getKey() == events.ENTER) {
var nextfld = field.nextSibling();
nextfld.focus(true,100);
}
}
specialkey - is a listener of component like textfield,textare,datefield etc,
events.getKey - gets the user keyboard input
events.ENTER - i used this for that will be triggered when "ENTER" in keyboard
field.nextSibling - field refers to current component, and nextSibling property of component to tell who will be the next component
lastly is the nextfld.focus to focus the next component

Related

Adding enabling and disabling as context menu on a grid in extjs

Hi I have added one context menu on my grid which will perform the enable and disable functionality for selected row. I am new to ExtJs. I have added below listener for the grid. How to add enable and disable functionality for the grid row?
listeners: {
itemcontextmenu: function (grid, record, item, index, e) {
var contextMenu = Ext.create('Ext.menu.Menu', {
controller: 'grid-controller',
width: 165,
plain: true,
items: [{
text: 'Disable',
listeners: {
click: {fn: 'disable', extra: record}
},
}]
});
e.stopEvent();
contextMenu.showAt(e.getXY());
}
}
This is not a copy-paste answer, but going through the following steps with doing your own research you can solve your problem.
1. Create the context menu only once and destroy it
In you code, the context menu is created every time when the user opens up the menu on the grid. This is not good. Instead, create the context menu only once when the grid is created, and destroy it when the grid is destroyed. Something like this:
Ext.define('MyGrid', {
extend: 'Ext.grid.Panel',
initComponent : function() {
this.callParent();
this.MyMenu = Ext.create('Ext.menu.Menu', {
items: [...]
});
this.on({
scope : this,
itemcontextmenu : this.onItemContextMenu
});
},
onDestroy : function() {
if (this.MyMenu) {
this.MyMenu.destroy();
}
},
onItemContextMenu : function(view, rec, item,index, event) {
event.stopEvent();
this.MyMenu.showAt(event.getXY());
}
});
2. Store enabled / disabled state in the record
For the next step to work, records in your grid must contain whether the corresponding row is enabled or disabled. In the context menu, when user selects enabled / disabled, store this status like this, get record of the row where the context menu was displayed from:
record.set('myDisabledState', true); // or false
It is important to store the disabled state (and not enabled), because when your grid initially is rendered, these values won't be in the records, so record.get('myDisabledState') will evaluate to FALSE, and that is the desired behaviour, if you want to start with every row being able to be selected.
3. Disable selection
Now you can add a beforeselect listener to your grid, see documentation. This listeners receives record as parameter, and if you return false from this listener, the selection will be canceled. So in this listener simply add:
listeners: {
beforeselect: function ( grid, record, index, eOpts ) {
return !record.get('myDisabledState');
}
}
4. Apply formatting - OPTIONAL
It is likely that you want to add different formatting for disabled rows, for example grey colour. The easiest way to do it is to add a custom CSS style to your Application.scss file:
.my-disabled-row .x-grid-cell-inner {
color: gray;
}
Finally add getRowClass configuration to your grid, it will receive the current record being rendered, and you can return the above custom CSS style when the row is disabled:
Ext.define('MyGrid', {
// your grid definition
,
viewConfig: {
getRowClass: function (record, rowIndex, rowParams, store) {
if (record.get('myDisabledState')) {
return "my-disabled-row";
}
}
}
});
In this last part, when row is not disabled, it will return nothing, so default formatting will be used.

ExtJS: Show/hide control on checkbox selectionchange

I have an ExtJS check-tree ExtJS Check Tree that I am trying to add some control to based on items checked/unchecked. It doesn't seem to fire correctly though.
Here is a Fiddle Example
When checkbox 'A' is selected, I want to hide the textfield, 'testValue', which works, but then if I unselect checkbox 'A', I want to show the textfield, 'testValue', which does not work.
For this test I am merely looking to see if the selections.selected.length === 0. However, when I unselect any of the checkboxes, the listener does not seem to be firing, since the alert message is not getting triggered - plus, if I then try to reselect the check box again it still does not fire.
I would use a selection Model (as outlined below) to achieve this (since I know it works), but then this places checkboxes on all my tree items when I just want to have the leaf nodes with checkboxes.
selModel: {
type: 'checkboxmodel',
listeners: {
selectionchange: 'onCheckedNodesChange'
}
}
Any suggestions would be most welcome!
EDIT
Adding allowDeselect: true and a listener for select and deselect sort of worked (I updated the Fiddle to exhibit the behavior):
selModel: {
allowDeselect: true,
listeners: {
deselect: function(model, record, index) {
text = record.get('text');
alert(text);
},
select: function(model, record, index) {
text = record.get('text');
alert(text);
}
}
},
I want to make sure that when 'A' is selected, the textfield remains hidden, but if you select another item in the list and then deselect it, the textfield returns.
I am trying to use the getChecked() method alone with when selectionchange event occurs. However, this only seems to return data when I do a submit (for example, on the Get checked nodes control). Any suggestions would be most welcome. This should not be so difficult.
For tree panel we have checkchange event it is similar to the selectionchange event.
http://docs.sencha.com/extjs/4.2.5/#!/api/Ext.tree.Panel-event-checkchange
checkchange( node, checked, eOpts )
Fires when a node with a checkbox's checked property changes
Parameters
node : Ext.data.TreeModel
The node who's checked property was changed.
checked : Boolean
The node's new checked state
eOpts : Object
The options object passed to Ext.util.Observable.addListener.
var fields = [
{
name: 'column'
},
{
name: 'leaf',
type: 'boolean'
},
{
name: 'checked',
type: 'boolean'
},
{
name: 'cls',
type: 'string',
defaultValue: 'x-tree-noicon'
},
];
this.dataModel = Ext.define('Filter-' + this.getId(), {
extend: 'Ext.data.Model',
fields: fields,
});
columns: [
{
xtype: 'treecolumn',
width: 200,
itemId: "filter",
dataIndex: 'column' ,
renderer: function (val, metaData, r) {
},
scope: this,
},
],
listeners: {
'checkchange': Ext.bind(function (node, checked,eOpts) {
},
scope: this
The checkboxes you are seeing are not part of the selection behaviour. Instead, they come from the checked configuration on the NodeInterface class.
Your tree panel is using the default selModel, which is row-based selection, with no deselect option. If you want the in-tree checks to control the selection, you'll need to configure that manually, probably by listening to change events from the store.
OTH, if all you care about is finding out which items are checked or not, you can use the getChecked() method on the TreePanel

Spellcheck for Extjs textfields

I need spellcheck in an extjs textfield. A textarea doesn't work because I need it to only allow a user to enter a single line of input - no enter key. Any way to enable spellcheck for the textfield?
I found a way to get around the single line requirement and use a textarea, which by default uses spellcheck. To force the textarea to be a single line add this to your textarea:
xtype: 'textarea',
grow: true,
growMax: 32,
enableKeyEvents: true,
listeneters: {
keydown: 'disableNewLine'
}
And in your controller, add the function to disable the new line.
disableNewLine: function(textarea, e, eOpt) {
if(e.keyCode == 13) {
e.stopEvent();
}
}
This prevents the user from adding a new line to their input just like a textfield would, but utilizes spellcheck. Also, 32 is the default height of a textfield, so it looks the exact same. Just setting the height doesn't work, the default seems to override that.
You can add it after the component is rendered.
Also make sure the browser you are using supports spell check.
http://caniuse.com/#search=spellcheck
{
xtype: 'textfield',
name: 'name',
fieldLabel: 'Name',
listeners: {
afterrender: function(cmp) {
cmp.getEl().set({
"spellcheck": 'true'
});
}
}
}
see api
inputAttrTpl: 'autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"'
It works fine under safari!
This override worked fine for me with ExtJS6 & Chrome:
Ext.define('Ext.overrides.form.field.Text',{
override: 'Ext.form.field.Base',
/**
* Ensure all text fields have spell check disabled
*/
inputAttrTpl: [
'spellcheck=false'
],
constructor: function () {
this.callParent(arguments);
}
});

keypress to delete value in 'open' datefield and close related datepicker

I have an ExtJS form.field.Date as below;
{
xtype: 'datefield',
name: 'X_Cut_Process_Completed_Date',
format: 'd M Y',
startDay: 1,
allowBlank: true,
editable: false,
listeners: {
specialkey: function(field, e){
if (e.getKey() == e.DELETE) {
field.setValue('');
}
}
}
}
I have been asked to implement an event that catches the Delete key while the datefield is being edited (with the associated datepicker open), that clears the value for the datefield and closes the datepicker. The existing specialkey listener only clears the value while the datefield is NOT being edited.
How do I implement a listener that closes a datefield's datepicker and clear the datefield's value simultaneously?
[UPDATE]
You can get the picker and hide it:
field.getPicker().hide()
I have tested it and it works. To test it for yoursef:
navigate to http://extjs.eu/software/form-field-icon-plugin/
in console type:
Ext.ComponentQuery.query('datefield')[0].on('specialkey', function(field, e){
if(e.getKey() === e.DELETE) {
field.getPicker().hide();
field.setValue('');
}
});
Now open the picker in the date field, type something and press delete. Both the field is cleared and the picker is hidden.

extjs onKeyEnter not firing

Hello i have the following RowEditing plugin i use
ar rowEditing = Ext.create('Ext.grid.plugin.RowEditing', {
clicksToMoveEditor: 1,
autoCancel: false,
errorSummary:false,
onEnterKey: function(e) { console.log(e); },
listeners:{
'beforeedit':function(grid,eOpts){
},
'canceledit':function(grid, eOpts){
if(grid.grid.store.data.getAt(0).data.id == "new"){
grid.grid.store.removeAt(0);
}
},
'afteredit':function(editor, changes, record, rowIndex){
editor.grid.store.reload();
},
'validateedit': handleUpdate{{params.alias}}
}
});
But the enter action is still performed and no console log is performed... i tried to put it inside the listeners as well but no change...
here's my item in my grid
{
header: 'Description',
width: 160,
align: 'left',
dataIndex: 'description',
filters: {
type: 'string'
},
enableKeyEvents: true,
editor: {
xtype: 'textfield',
allowBlank: false,
listeners: {
keydown: {
element: 'el',
fn: function(el){
if (el.ENTER){
alert('test');
return false;
}
}
},
},
}
}
so my next try as to 'disable' the firing of the enter (or submitting the rowedit) inside the field itself. but a return false still submits the form, and a onEnterKey doesn't work there either... anyone has an idea what i am doing wrong?
I did find that onEnterKey is part of the parent Editing class but it doesn't say how i should call that..
First of all, onEnterKey is marked as private, so you shouldn't be overriding it, especially not upon instantiation. If you want to override class methods, you should do that by creating a new class which inherits from the class containing the methods:
Ext.define('My.grid.plugin.Editing', {
extends: 'Ext.grid.plugin.RowEditing',
onEnterKey: function() {
this.callParent(arguments);
// your code here
}
});
Regarding your problem, I suggest one of the following approaches:
A) If you really want to disable the ENTER key event only, you should do that on the editor field(s). Your attempt was close, but the event listener was not doing the right things yet:
editor: {
allowBlank: false,
listeners: {
keydown: function(e){
if (e.getKey() == e.ENTER){
e.stopEvent();
}
}
}
}
Note that with this approach the user will still be able to submit any change by just clicking the "Update" button of the row editing plugin.
B) If you just want to prevent the editing plugin from writing the changes to the store under certain conditions, you can also use the validateedit event on the editing plugin:
listeners: {
validateedit: function(editor, e) {
if (true) { // your condition here
return false;
}
}
}
This will also work, if the user clicks on the "Update" button.

Resources