I want to select and deselct combobox items using space key. In the existing functionality it happens with Enter key.
I have the following code which is not working and giving error deep inside the sencha files.Here me is the combobox.
keydown: function (me, e, eOpts) {
me.keyPressed = e.getKey();
if (me.keyPressed == 32) {
e.keyCode = Ext.EventObject.ENTER;
this.fireEvent(e);
}
}
The way to go is to modify the key bindings of the KeyNavigation of the picker.
listeners:{
afterrender:function(combo) {
var picker = combo.getPicker(),
navModel = picker.getNavigationModel(),
map = navModel.keyNav.map,
existingBindings = Ext.Array.filter(map.bindings, function(binding) {
return binding.key === Ext.event.Event.SPACE;
};
map.removeBinding(existingBindings[0]);
map.addBinding({
key: Ext.event.Event.SPACE,
fn: navModel.onKeyEnter,
scope: navModel
});
}
}
Related
I create a grid and a toolbar with Two Menu of menuCheckItem. When i check the menuCheckItem the grid filters even with multiple values and multiple columns.
This working fine, as I have created grid 1st and then the toolbar
this.up('') // Used Instead of Ext.getCmp()
Working FIDDLE - https://fiddle.sencha.com/#view/editor&fiddle/2lop
Now I am trying to create same toolbar along with Menu separately on top 1st and then create grid at below. But while doing this, nly Multiple values is working.
I am trying to filter grid with multiple values as well as multiple columns.
Few things i tried -
// Only Filters One Value at a time with each Columns
store.queryBy(function(record,id){
return (record.get('name') == someValue && record.get('phone') == otherValue);
});
and
// Filters Many Columns with Single Value
filter.add(
property : name, phone
value : "somevalue"
operator : "OR"
);
Is there any way to implement Toolbar 1st and then grid ? And Filter grid with many values and columns simultaneously ?
In this FIDDLE i remade a function(checkchange), which is universal , can be put separately and you'll be able to attach it to every menucheckitem you create. The only thing is that if you add new menucheckitem filter you should name the menucheckitem id with the name of the columnDataIndex-Menu and add this columnDataIndex in menuFilters and thats all.
checkchange: function (checkbox, checked, eOpts) {
var menuFilters = ['name', 'phone'];
var getChecked = function (m) {
var checkedItems = [];
m.items.items.forEach(function (c) {
if (c.checked) {
checkedItems.push(c.text);
}
});
return checkedItems;
};
//
var menus = new Map();
menuFilters.forEach(function (e) {
menus.set(e, Ext.getCmp(e + '-Menu'));
});
//
var fieldValues = [];
menuFilters.forEach(function (e) {
fieldValues.push([e, getChecked(menus.get(e))]);
});
//
var store = checkbox.up('grid').store;
store.clearFilter();
//
if (fieldValues.length > 0) {
store.filterBy(function (record) {
var fV = this.fieldValues;
for (var i = 0; i < fV.length; i++) {
if (fV[i][1].length > 0) {
if (fV[i][1].indexOf(record.get(fV[i][0])) === -1) {
return false;
}
}
}
return true;
}, {
fieldValues: fieldValues
});
}
}
I'm using 'ui.bootstrap.contextMenu' to build a context menu. When I right click a field, I need to pass in a unique ID, to the controller, and return a list of choices based on the ID. Each list could be different. If I use hardcoded list, it works fine, but I can't seem to generate the list dynamically. What am I missing? Example Code:
`<div>
<textarea ng-model="ctrl.status" context-menu="ctrl.menuOptions (ctrl.id)"></div>
</div>
vm.menuOptions = function(id) = {
var listArray = $scope.list; // array of possible list items based on ID
angular.forEach(listArray, function(value, key) {
if (id === value.id) {
return [
[value.id, function ($itemScope) {
return value.textName;
}],
]
}
}
}`
I'm assuming you're referring to this implementation: https://github.com/Templarian/ui.bootstrap.contextMenu
The function to generate the context menu is passed three things:
$cmScope - the scope of the context menu
event - the event object that triggered the opening of the context menu
modelValue - the value of the ng-model attached to the current object
So, in your example, you can use:
vm.menuOptions = function($cmScope, event, modelValue) = {
var listArray = $scope.list; // array of possible list items based on ID
// ^ Assuming that the $scope here is the scope of the container, not the contextmenu
angular.forEach(listArray, function(value, key) {
if (modelValue === value.id) {
return [
[value.id, function ($itemScope) {
return value.textName;
}],
]
}
}
}
This is how I did coding, please help me to disable particular column:
listeners: {
beforeedit: function(obj) {
debugger;
var c = obj.record.get('quarterlyreview1');
if(c==="Approved") {
var d = obj.record.get('quarterlyprogress1');
obj.record.cancelEdit();
}
// return obj.record.get('status');
// you can update the above logic to something else
// based on your criteria send false to stop editing
}
},
According to the Documentation if beforeedit returns false the edit is stopped.
(This code would work for V4 and V5)
listeners: {
beforeedit: function(editor, context, eOpts) {
debugger;
var c = context.record.get('quarterlyreview1');
if(c==="Approved" && (context.colIdx==0 || context.colIdx==1)) {
return false;
}
// return context.record.get('status');
// you can update the above logic to something else
// based on your criteria send false to stop editing
}
},
I need keep the default feature of reordering columns and add
possibility drop the column in a second grid, building in the last a list
with the columns of first grid.
I hope has been clear.
I solved the issue extending DropZone. This implementation receive as constructor param the target grid, and this, be in the rbar (docked control) of source grid. The key is set ddGroup to "header-dd-zone-" plus id from source grid. I hope this is useful.
Ext.define('Crud.FilterDropZone', {
extend: 'Ext.dd.DropZone'
, constructor: function() {}
, init: function (grid) {
var me = this;
if (grid.rendered) {
me.grid = grid;
me.ddGroup = 'header-dd-zone-' + grid.up('grid').id;
grid.getView().on({
render: function(v) {
me.view = v;
Crud.FilterDropZone.superclass.constructor.call(me, me.view.el);
},
single: true
});
} else {
grid.on('render', me.init, me, {single: true});
}
}
, getTargetFromEvent: function (e) {
return {};
}
, onNodeDrop: function (nodeData, source, e, data) {
var header = data.header
, store = Ext.getCmp(e.target.id).getStore();
//store.add(new store.RecordType({ property: header.text, value: '', reference: header.dataIndex}));
store.add([[header.text, '', header.dataIndex]]);
}
});
I am using ext js to drag and drop data from one dataview to another. I want to know if the drop event happened on top of an existing node or if it was just dropped in the white space of the dataview.
Here's the code for my dropTarget:
...
onDesktopDataViewRender: function (v) {
var dataView = v;
v.dropTarget = Ext.create('Ext.dd.DropTarget', v.el, {
ddGroup: 'FromSearchToDesktop',
notifyDrop: function (source, e, dropData) {
//Want do do something like:
//if(dropped directly on any node) {
// do some logic with that node
//}
//else {
// do the code below
var recordAlreadyExists = false;
v.store.each(function (r) {
if (r.data.ID == dropData.searchData.ID) {
recordAlreadyExists = true;
}
});
if (recordAlreadyExists == false) {
v.store.add(dropData.searchData);
}
//end else
}
});
}
...
Yay! Finally figured this one out.
The quick answer is to create a DropZone for the node. The long answer is how to do that.
In my program, the user can drag items from DataView A to DataView B. After dropping the item in DataView B, the item appears in DataView B. On top of that, the user can drag an item from DataView A, and drop it on a node inside DataView B. The code needs to differentiate between the item being dropped on the DataView and the item being dropped on a node inside the DataView.
Generic instructions:
In DataViewB's onrender event, create a dropTarget with a ddGroup of
"DataViewB"
Inside the notifyDrop function, create a new node.
Also inside the notifyDrop function, create another dropTarget
(this one for the node instead of the DataView) with a ddGroup of "DataViewBNode".
Inside DataViewA's onRender event, create a DragZone with a ddGroup
of "DataViewBNode" (!important!)
Inside of DataViewA's afterrender event, add the dragZone to the
"DataViewB" group.
Now you will be able to drag from DataViewA and drop in the white space of DataViewB to add a node, but you will also be able to drop directly on a node from DataViewB and do a different action.
It's very important that the first ddGroup is for the node, and the one that's added in the afterrender event is for the DataView
Here is the code for DataView A:
onDataViewARender: function (v) {
var dataView = v;
...
v.dragZone = Ext.create('Ext.dd.DragZone', v.getEl(), {
ddGroup: 'DataViewBNode',
getDragData: function (e) {
var sourceEl = e.getTarget(v.itemSelector, 10), d;
if (sourceEl) {
d = sourceEl.cloneNode(true);
d.id = Ext.id();
return v.dragData = {
sourceEl: sourceEl,
repairXY: Ext.fly(sourceEl).getXY(),
ddel: d,
searchData: v.getRecord(sourceEl).data,
store: v.store,
source: 'DataViewA'
}
}
},
getRepairXY: function () {
return this.dragData.repairXY;
}
});
},
onDataViewAAfterRender: function(v) {
var dragZone = v.dragZone;
dragZone.addToGroup('DataViewB');
},
Here is the code for DataViewB
onDataViewBRender: function (v) {
var dataView = v;
v.dropTarget = Ext.create('Ext.dd.DropTarget', v.el, {
ddGroup: 'DataViewB',
notifyDrop: function (source, e, dropData) {
var recordAlreadyExists = false;
v.store.each(function (r) {
if (r.data.ID == dropData.searchData.ID && r.data.Type == dropData.searchData.Type) {
recordAlreadyExists = true;
}
});
if (recordAlreadyExists == false) {
v.store.add(dropData.searchData);
var nodes = v.container.dom.childNodes[0].childNodes;
var index = v.container.dom.childNodes[0].childNodes.length -1;
//
//Here is where you create the dropTarget for the new node
//
nodes[index].dropTarget = Ext.create('Ext.dd.DropTarget', nodes[index], {
ddGroup: 'DataViewBNode',
notifyDrop: function (source, e, dropData) {
console.log('success')
}
});
}
}
});
...
},