The Ext.grid.plugin.DragDropView and Ext.tree.plugin.TreeViewDragDropView are great to allow drag'n'drop functionnality over those components but I don't want the store modification thing when I drag and drop an item.
I want custom functions, like, when I drop an item on my grid, I don't want the drag component source store to be modified and I don't want the drop component store to be modified too. I would like a function of mine to be called instead.
How to do this?
Do I need to use DragZone and DropZone instead?
You are on the right path, and looking in the right areas. The plugins that you have mentioned are exactly what you need for this purpose and provide the DragZone and DropZone functionality within.
I have written a simple example of using these plugins together, Fiddle Here.
The thing to watch out for here... If you do not want the default functionality of moving a record between stores you will likely need to run your own logic in the beforeDrop event and call the cancelDrop method, to prevent default behaviour, this is demonstrated in the fiddle and code below.
Make sure that both plugins share the same ddGroup.
Ext.application({
name: 'Fiddle',
launch: function() {
// create a very simple tree view
var treeStore = Ext.create('Ext.data.TreeStore', {
root: {
expanded: true,
children: [{
text: "detention",
leaf: true
}, {
text: "homework",
expanded: true,
children: [{
text: "book report",
leaf: true
}, {
text: "algebra",
leaf: true
}]
}, {
text: "buy lottery tickets",
leaf: true
}]
}
});
var gridStore = Ext.create('Ext.data.Store', {
storeId: 'simpsonsStore',
fields: ['name', 'email', 'phone'],
data: {
'items': [{
'name': 'Lisa',
"email": "lisa#simpsons.com",
"phone": "555-111-1224"
}, {
'name': 'Bart',
"email": "bart#simpsons.com",
"phone": "555-222-1234"
}, {
'name': 'Homer',
"email": "homer#simpsons.com",
"phone": "555-222-1244"
}, {
'name': 'Marge',
"email": "marge#simpsons.com",
"phone": "555-222-1254"
}]
},
proxy: {
type: 'memory',
reader: {
type: 'json',
rootProperty: 'items'
}
}
});
Ext.create('Ext.panel.Panel', {
renderTo: Ext.getBody(),
layout: 'fit',
height: 800,
width: 800,
items: [{
layout: 'border',
title: "DnD",
height: '100%',
items: [{
xtype: 'grid',
region: 'center',
store: gridStore,
columns: [{
text: 'Name',
dataIndex: 'name'
}, {
text: 'Email',
dataIndex: 'email',
flex: 1
}, {
text: 'Phone',
dataIndex: 'phone'
}],
viewConfig: {
plugins: {
ptype: 'gridviewdragdrop',
enableDrag: false,
enableDrop: true,
ddGroup: 'myDropGroup'
},
listeners: {
beforedrop: function(node, data, overModel, dropPosition, dropHandlers) {
// Defer the handling
dropHandlers.wait = true;
// here you have the record from the treeview and can do anything you like with it.
var record = data.records[0];
Ext.MessageBox.confirm('Drop', 'Your are about to drop ' + record.get('text') + ', Are you sure?', function(btn) {
if (btn === 'yes') {
dropHandlers.processDrop();
} else {
// IMPORTANT - In this case, we want to cancel the drop as the records aren't compatible
dropHandlers.cancelDrop();
}
});
}
}
}
}, {
xtype: 'treepanel',
width: '40%',
region: 'west',
store: treeStore,
rootVisible: false,
viewConfig: {
plugins: {
ptype: 'treeviewdragdrop',
enableDrop: false,
ddGroup: 'myDropGroup'
}
}
}]
}]
});
}
});
Related
I am trying to use templatecolumn in EXTJS modern toolkit. I cannot figure out why Ext.XTemplate doesn't work in modern toolkit, because the syntax is not different than that for classic toolkit.
Code
var store = Ext.create('Ext.data.Store', {
fields: ['name'],
data: [{
'name': 'Bart',
}, {
'name': 'Lisa',
}, {
'name': 'Homer',
}, {
'name': 'Marge',
}]
});
Ext.create({
xtype: 'grid',
height: 500,
renderTo: Ext.getBody(),
store: store,
columns: [
{text: 'Name', dataIndex:'name'},
{
text: 'Name Styled',
xtype: 'templatecolumn',
tpl: new Ext.XTemplate(
'<div class="myClass">{name}</div>',
),
},
],
});
CSS
.myClass {
font-size: 16px;
color: red;
}
And for classic toolkit, it renders well:
but, for modern toolkit, it displays full html text, instead to apply class:
Just set encodeHtml to false in cell config:
var store = Ext.create('Ext.data.Store', {
fields: ['name'],
data: [{
'name': 'Bart',
}, {
'name': 'Lisa',
}, {
'name': 'Homer',
}, {
'name': 'Marge',
}]
});
Ext.create({
xtype: 'grid',
height: 500,
renderTo: Ext.getBody(),
store: store,
columns: [{
text: 'Name',
dataIndex: 'name'
}, {
text: 'Name Styled',
// disable enocde in cell
cell: {
encodeHtml: false
},
// ----
tpl: new Ext.XTemplate('<div class="myClass">{name}</div>'),
}, ],
});
I don't get it, according to the manual for ExtJs 7.3 Modern it should be possible to configure a Ext.grid.Grid (https://docs.sencha.com/extjs/7.3.0/modern/Ext.grid.Grid.html#cfg-stateful).
I've added:
({
// ...
stateId: 'state-grid',
stateful: true,
// ...
});
and on the columns also added an stateId for each column and in the applications launch function I've added:
launch: function() {
Ext.state.Provider.register(new Ext.state.LocalStorage());
Ext.get(Ext.query('#appLoadingIndicator')).remove();
this.callParent(arguments);
}
But I dont get the stateful grid to work, i.e. I hide a column and then refresh the site.. the column is still visible. So does stateful work at all in ExtJs 7.3 MODERN <--- Modern not classic.
Have a look at the following self-explainable fiddle sample. It saves the width and hidden properties of the grid column:
Ext.application({
name: 'Fiddle',
launch: function () {
Ext.state.Provider.register(new Ext.state.LocalStorage());
var store = Ext.create('Ext.data.Store', {
fields: ['name', 'email', 'phone'],
data: [{
'name': 'Lisa',
"email": "lisa#simpsons.com",
"phone": "555-111-1224"
}, {
'name': 'Bart',
"email": "bart#simpsons.com",
"phone": "555-222-1234"
}, {
'name': 'Homer',
"email": "home#simpsons.com",
"phone": "555-222-1244"
}, {
'name': 'Marge',
"email": "marge#simpsons.com",
"phone": "555-222-1254"
}]
});
var grid = Ext.create('Ext.grid.Grid', {
title: 'Simpsons',
columns: [{
text: 'Name',
dataIndex: 'name',
stateId: 'name-column-state-id',
stateful: {
// we will state hidden and width of the column states only
hidden: true,
width: true
}
}, {
text: 'Email',
dataIndex: 'email',
stateId: 'email-column-state-id',
stateful: {
// we will state hidden and width of the column states only
hidden: true,
width: true
}
}, {
text: 'Phone',
dataIndex: 'phone',
stateId: 'phone-column-state-id',
stateful: {
// we will state hidden and width of the column states only
hidden: true,
width: true
}
}],
store: store,
layout: 'fit',
fullscreen: true
});
}
});
help me understand the tree filtering.
I have input ow
xtype: 'triggerfield',
listeners: {
change: function() {
console.log()
}
}
How can I filter the tree? I need to send a request to the server with a value from the field
You can use filterBy method to do simple or complex filtering on TreeStore:
var store = Ext.create('Ext.data.TreeStore', {
autoload: true,
root: {
expanded: true,
specialProp: 1,
children: [{
text: "detention",
leaf: true,
specialProp: 1
}, {
text: "homework",
expanded: true,
children: [{
text: "book report",
leaf: true,
specialProp: 1
}, {
text: "algebra",
leaf: true,
specialProp: 2
}]
}, {
text: "buy lottery tickets",
leaf: true,
specialProp: 1
}]
}
});
Ext.create('Ext.container.Viewport', {
layout: 'fit',
items: [{
xtype: 'container',
items: [{
xtype: 'treepanel',
id: 'treePanelId',
store: store,
dockedItems: [{
xtype: 'toolbar',
items: [{
xtype: 'button',
text: 'specialProp=1 Filter',
handler: function () {
var treePanel = Ext.getCmp('treePanelId');
treePanel.getStore().filterBy(function (item) {
if (item.get('root') === true) return true;
else if (item.get('specialProp') === 1) return true;
else return false;
});
}
}, {
xtype: 'button',
text: 'Clear filter',
handler: function () {
var treePanel = Ext.getCmp('treePanelId');
treePanel.getStore().clearFilter();
}
}]
}]
}]
}]
});
Example Fiddle: https://fiddle.sencha.com/#view/editor&fiddle/29si
EDIT:
For remote filtering you can do it like following:
var store = Ext.create('Ext.data.TreeStore', {
remoteFilter: true,
proxy: {
type: 'ajax',
url: 'data.json',
reader: {
type: 'json'
}
},
root: {
expanded: true
}
});
Ext.create('Ext.container.Viewport', {
layout: 'fit',
items: [{
xtype: 'container',
items: [{
xtype: 'treepanel',
id: 'treePanelId',
store: store,
dockedItems: [{
xtype: 'toolbar',
items: [{
xtype: 'button',
text: 'specialProp=1 Filter',
handler: function () {
var treePanel = Ext.getCmp('treePanelId');
treePanel.getStore().filter('specialProp', 1);
}
}, {
xtype: 'button',
text: 'Clear filter',
handler: function () {
var treePanel = Ext.getCmp('treePanelId');
treePanel.getStore().clearFilter();
}
}]
}]
}]
}]
});
Remote Sort Fiddle Example: https://fiddle.sencha.com/#view/editor&fiddle/29sq
Take a look at response of request, you can filter on server side with this. Also for ease of understanding I have put params in response to show how filters would be actually appear on http request which need to be processed.
Note: Make sure you send data response in following format:
{ status: 'success', children: [{...}, {...}, ....] }
If you are sending response in other format you will need to process it in store proxy.
I am using EXTJS and I want to create my TreePanel with one more icon to the right that will be set to indicate something has changed. I am struggling to do this as I am unsure where I can modify these properties. It would be easy with HTML alone but obviously this framework is useful and I need to integrate these changes into it.
Thanks,
Dan
Yes, there is way to handle it in ExtJS framework with renderer method on column.
Here is how I would achieve it using ExtJS 6.0.x:
Ext.create('Ext.container.Viewport', {
layout: 'fit',
items: [{
xtype: 'container',
scrollable: 'y',
flex: 1,
layout: {
type: 'hbox',
alignt: 'stretchmax'
},
items: [{
xtype: 'treepanel',
rootVisible: false,
flex: 1,
store: {
type: 'tree',
parentIdProperty: 'parentId',
root: {
text: 'Navigation Bar',
expanded: true,
children: [{
text: 'Parts',
children: [{
leaf: true,
itemId: 'addPart',
text: 'Add new part',
changed: true
}, {
leaf: true,
itemId: 'manageParts',
text: 'Manage Parts',
changed: false
}, ]
}, {
leaf: true,
itemId: 'announcements',
text: 'Announcements',
changed: true
}]
}
},
columns: [{
text: 'Code',
dataIndex: 'codigo',
align: 'left'
}, {
xtype: 'treecolumn',
text: 'Description',
dataIndex: 'text',
flex: 1
}, {
text: 'Edited',
iconCls: 'x-fa fa-edit',
align: 'center',
flex: 1,
renderer: function (f, grid, record) {
if(record.get('changed') === true) {
return "Changed Icon here"
}
else {
return "Not changed icon here";
}
}
}]
}]
}]
});
With this you can easily manage the data with store and can easily update the data in store. ExtJS will take care of rendering the given configuration for columns.
You can also use actioncolumn to show icons/buttons and handle events with listeners.
Example Fiddle: https://fiddle.sencha.com/#view/editor&fiddle/28qm
I Have solved the problem. You can embed html into the text field in the store.
Ext.define('MyApp.store.Navigation', {
extend: 'Ext.data.TreeStore',
alias: 'store.navigation',
rootData: {
text: 'Navigation Bar',
expanded: true,
children: [
{
text: 'Parts',
children: [
{ leaf:true, itemId:'addPart', text: 'Add new part' },
{ leaf:true, itemId:'manageParts', text: 'Manage Parts <b>here</b>' },
]
},
{
leaf:true, itemId:'announcements', text: 'Announcements'
}
]
},
constructor: function (config) {
// Since records claim the data object given to them, clone the data
// for each instance.
config = Ext.apply({
root: Ext.clone(this.rootData)
}, config);
this.callParent([config]);
}
});
Probably a poor solution but gets the job done.
I am developing a web application in ExtJS. The application is a grid where some of the grid`s rows can be expanded to show supplementary information as a nested grid. And user can edit rows in parent grid.
But I have problems with it. The nested grid is normally rendered , but when I want to update one of the field nested grid disappear.
There is testing version of my application and some screenshots.
The Code ( below you can find screens)
Ext.onReady(function() {
Ext.create('Ext.data.Store', {
storeId: 'simpsonsStore',
fields: ['name', 'email', 'phone'],
data: {
'items': [{
'name': 'Lisa',
"email": "lisa#simpsons.com",
"phone": "555-111-1224"
},
{
'name': 'Bart',
"email": "bart#simpsons.com",
"phone": "555-222-1234"
},
{
'name': 'Homer',
"email": "home#simpsons.com",
"phone": "555-222-1244"
},
{
'name': 'Marge',
"email": "marge#simpsons.com",
"phone": "555-222-1254"
}
]
},
proxy: {
type: 'memory',
reader: {
type: 'json',
root: 'items'
}
}
});
Ext.create('Ext.grid.Panel', {
title: 'Simpsons',
plugins: [{
ptype: 'rowexpander',
pluginId: 'courseListGridExpander',
expandOnDblClick: false,
selectRowOnExpand: false,
enableCaching: false,
rowBodyTpl: ['']
},
Ext.create('Ext.grid.plugin.RowEditing', {
clicksToMoveEditor: 2,
autoCancel: false
})
],
viewConfig: {
listeners: {
expandbody: function(rowNode, record, expandbody) {
var targetId = 'SessionInstructionGridRow';
if (Ext.getCmp(targetId + "_grid") == null) {
var sessionInstructionGrid = Ext.create('Ext.grid.Panel', {
renderTo: targetId,
id: targetId + "_grid",
title: 'Nested One',
columns: [{
header: 'Halo',
flex: 1
},
{
header: 'Halo 2',
flex: 1
}
]
});
rowNode.grid = sessionInstructionGrid;
sessionInstructionGrid.getEl().swallowEvent(['mouseover', 'mousedown', 'click', 'dblclick', 'onRowFocus']);
sessionInstructionGrid.fireEvent("bind", sessionInstructionGrid, {
ClientSessionId: record.get('ClientSessionId')
});
}
},
celldblclick: function(gr, td, cellIndex, record) {
//alert("###");
}
}
},
store: Ext.data.StoreManager.lookup('simpsonsStore'),
columns: [{
text: 'Name',
dataIndex: 'name',
editor: {
allowBlank: false
}
},
{
text: 'Email',
dataIndex: 'email',
flex: 1
},
{
text: 'Phone',
dataIndex: 'phone'
}
],
height: 200,
width: 400,
renderTo: Ext.getBody()
});
Ext.create('Ext.button.Button', {
text: 'Hello',
handler: function() {
}
})
});
I would give the ComponentRowExpander plugin a try. It's intended to insert any component in a rowexpander - so it should work with a grid, too.