I have a gridpanel that allows inline editing of a column. This column uses a combobox as the editor, and neither the "change" event nor the "select" event give me something usable to backtrace the edited value to get the changed row from the gridpanel.
I believe Ext floats the editor's combobox so therefore I can't do something simple like
combo.up()
To return to the grid.
Here is the grid panel from the view:
{
xtype: 'gridpanel',
title: 'Important Projects',
id: 'importantProjectsGrid',
dockedItems: [],
flex: 1,
columns: [
{ header: 'Quote Name', dataIndex: 'QuoteName', flex: 4 },
{ header: 'Quote Status', dataIndex: 'QuoteStatusID', flex: 6, editor: {
xtype: 'combobox',
editable: false,
action: 'QuoteStatus',
selectOnTab: true,
store: 'statuses',
queryMode: 'local',
displayField: 'Description',
valueField: 'Description'
} }
],
store: 'myimpprojects',
selModel: {
selType: 'cellmodel'
},
plugins: [Ext.create('Ext.grid.plugin.CellEditing', {
clicksToEdit: 1
})]
}
Here is the controller code pertaining to this:
init: function () {
this.control({
'[action=QuoteStatus]': {
change: function (combo, new_value, old_value, opts) {
// I need to go back up from this combobox
// to get the row that this value was edited in
// to grab an ID value from that row's data
// in order to make an ajax request
}
}
});
},
Thanks for any help!
You can monitor store's update event.
init: function () {
this.getMyimpprojectsStore().on('update', function(store, record) {
// do something with record
});
// ...
},
Try putting the listener on the CellEditing plugin. There are events for beforeedit, edit, and validateedit that receive an object containing references to the grid, the record, field, row and column indexes, and more. You should be able to check for the combobox in the event handler and handle your information from there.
Quick link to the doc page: Ext.grid.plugin.CellEditing
I'm convinced that the update plugin will handle the update automatically, through the api of the underlying store and post the data automatically to the server if the proxy as autoSync to true.
Example of the configured proxy:
Ext.define('MyApp.store.YourStore', {
extend: 'Ext.data.Store',
model: 'MyApp.model.YourGridModel',
autoSync: true, //Commits the changes realtime to the server
proxy: {
type: 'ajax',
batchActions : true, //Commits the changes everytime a value is changed if true o otherwise store the changes and batch update them in 1 single post
api: {
read: 'path/to/select',
create: 'path/to/create',
update: 'path/to/update',
destroy: 'path/to/delete'
},
reader: {
type: 'json',
root: 'results',
successProperty: 'success'
},
writer: {
type: 'json',
writeAllFields: true
},
listeners: {
exception: function(proxy, response, operation){
Ext.MessageBox.show({
title: 'REMOTE EXCEPTION',
msg: operation.getError(),
icon: Ext.MessageBox.ERROR,
buttons: Ext.Msg.OK
});
}
}
},
listeners: {
write: function(proxy, operation){
var response = Ext.JSON.decode(operation.response.responseText);
if(response.success == true)
{
//TODO: Proxy - Messageboxes might be a little anoying we might instead use the status bar in teh grid or something so show status of the operation
Ext.MessageBox.show({
title: this.xFileLibraryTitle,
msg: response.message,
icon: (response.success == true)? Ext.MessageBox.INFO : Ext.MessageBox.ERROR,
buttons: Ext.Msg.OK
});
}
}
}
});
I would look specially for the two configs: "autoSync" and "batchActions"
Hope this helps you further with your issue!
Related
How to populate the combo box with uppercase value items for the below: Thank you
I have below code 1 and store in the view calling web api as in store reader in code 2:
Code 1 :
comboBox.store.load({
callback: function () {
comboBox.setValue(params.val)
}
});
Code 2 :
Ext.define('App.View.Value', {
extend: 'Ext.form.field.ComboBox',
alias: 'widget.App-View-Value',
labelAlign: 'right',
emptyText: 'Value',
valueField: 'Id',
displayField: 'Name',
forceSelection: true,
allowBlank: false,
editable: false,
triggerAction: 'all',
lastQuery:'',
store: {
type: 'webapi',
autoLoad: false,
api: {
read: 'api/filter/getVal'
}
}
});
You can do it by iterating over records in store's callback function.
Code snippet:
comboBox.store.load({
callback: function (records, operation, success) {
records.forEach(function (rec, index) {
rec.set('Name', rec.get('Name').toUpperCase());
})
}
});
Working Example
Hope this will help/guide you.
If params.val is a String you can do a UpperCase transformation with .toUpperCase() like this
comboBox.store.load({
callback: function () {
comboBox.setValue(params.val.toUpperCase())
}
});
I am trying to make my grid.Panel cells editable with one click. I have following code that doesn't work. I followed this this link and implemented in my program but still clicking doesn't enable editing. I also tried RowEditing but it didn't work either. There is no problem getting info from database.
Ext.define('CategoryNumberGrid', {
extend: 'Ext.grid.Panel',
selType: 'cellmodel',
pageSize: 25,
defineColumns:function(){
this.columns=[
{
header: 'Code',
dataIndex: 'code',
renderer: Ext.util.Format.htmlEncode
},{
header: 'Description',
dataIndex: 'descr',
renderer: Ext.util.Format.htmlEncode
}];
},
model: 'CategoryNumberModel',
initComponent:function(){
this.defineColumns();
var config = {
autoLoad: true,
autoSync: true,
remoteFilter: true,
remoteSort: true,
proxy: getProxy("CategoryNumberModel"),
model: 'CategoryNumberModel',
sorters:[
{
property:'code',
direction:'ASC'
}],
pageSize: this.pageSize
};
this.Store = Ext.create('Ext.data.Store', config);
this.editing = Ext.create('Ext.grid.plugin.CellEditing', {
clicksToEdit:1});
this.plugins=[this.editing];
this.callParent();
}
});
Your sample is not complete (not runnable) as per the question guidelines.
JavaScript is case-sensitive. this.Store won't help a grid to find its data.
Your columns are lacking the editor config.
I have corrected the issues: https://fiddle.sencha.com/#fiddle/1f41
For future questions, please consider making a working fiddle that exhibits the problem.
I've searched the net for answer but didn't find anything. Hope you can help.
So I am relativly new to extJs. I have a navigation bar on the left. When I press the first button there, a new window opens, which contains a table and loads its data automatically. The first time it works perfect but when I close the window and open it again I get the error "cannot call method getRange of null".
If I open the second window (when I click the other button in my navigation bar), I have 4 tabs, which contain a table each. Each Tab has a toolbar with buttons (create, change, etc.). Here happens the same thing as by the first window.
I can also print those tables as a List and the first time works fine, but when I cancel the print action I get the error again.
I made sure that all buttons and tables have a different reference, so I really don't know what this could be.
Any ideas?
I add my panels, which will open the new windows here:
items: [
{
xtype: 'tabpanel',
region: 'center',
items: [{
// 1. Tab
xtype: 'componentTap-panel',
title: UMA.Locale.rm.component.componentTitle,
id: 'componentTab'
}, {
// 2. Tab
title: UMA.Locale.rm.componentGroup.componentGroupTitle,
xtype: 'componentGroupTap-panel',
id: 'componentGroupTab'
}, {
// 3. Tab
title: UMA.Locale.rm.componentTemplateTitle,
xtype: 'componentTamplate-panel',
id: 'componentTemplateTab'
},
{
//4.Tab
title: UMA.Locale.rm.inventoryTitle,
xtype: 'inventoryTab-panel',
id: 'inventoryTab'
}
]
}
]
When the window opens I add my table and toolbar:
items: [{
xtype: 'toolbar',
region: 'north',
reference: 'componentToolbar',
items: [{
text: UMA.Locale.rm.buttonCreate,
action: 'createComp'
}, {
text: UMA.Locale.rm.buttonChange,
action: 'changeComp'
}, {
text: UMA.Locale.rm.buttonMove,
action: 'moveComp'
}, {
text: UMA.Locale.rm.buttonDelete,
action: 'deleteComp'
},{
text: UMA.Locale.rm.buttonPrint,
action: 'print',
margin: {
left: 8
}, {
xtype: 'componentTable-panel',
region: 'center'
}, {
xtype: 'componentsFilter-panel',
width: 300,
region: 'east'
}]
and then autoload my table:
items:[{
xtype: 'filtergrid',
reference: 'componentGrid',
paging: true,
hideHeaders: false,
region: 'center',
selModel: new Ext.selection.RowModel({
mode: "MULTI"
}),
store: {
model: 'Component',
autoLoad: true
},
columns: [{ ...
As Sergey Novikov mentioned that getRange() is a store method.
I also faced the same error for my grid's store and after some review again and again I found that whenever I close the tab and reopen it again I am getting two instance of grid's view (which can be checked by grid.getView()) and then I reached a conclusion that whenever the grid is creating the second time the selection model of grid view is having two instances because of I am using the code for selModel as new Ext.selection.CheckboxModel({
showHeaderCheckbox: true,
width: 50,
mode: 'MULTI'
})
then I changed the code for selModel as
selModel: {
selType: 'checkboxmodel',
showHeaderCheckbox: true,
width: 50,
mode: 'MULTI'
}
and the error is gone for me.
Hope this will help you. :)
Use the Object() constructor to test whether the object is one of three subtypes:
null object
object object
array object
For example:
function foo() { return {"hi":"bye" } }
function bar() { return null }
function baz() { return [1,2,3] }
function testObject(myObject)
{
if (Object(myObject).hasOwnProperty("0") )
{
/* Call getRange */
return 'yes';
}
else
{
/* throw an exception */
return 'no';
}
}
console.log(testObject(foo()), testObject(bar()), testObject(baz()) );
Having a problem with ExtJS when it comes to dragging from a tree to another tree.
I have one tree, sourceTree, that has all the elements available to drag from.
I have another tree, targetTree that will hopefully contain all the elements dragged (selected) from the source tree.
var sourceStore = Ext.create('Ext.data.TreeStore', {
model: 'MyTreeModel',
proxy: {
type: 'ajax',
url: '/some_action_that_returns_tree_json',
extraParams: { /*extra params*/
},
reader: {
type: 'json',
root: function (o) {
if (o.children == null) {
return o.children;
} else {
return o;
}
}
}
},
folderSort: true
});
the source tree is defined as:
{
xtype: 'treepanel',
flex: 5,
iconCls: 'myiconcls',
border: true,
store: formstore,
loadMask: true,
rootVisible: false,
title: 'Source',
bodyStyle: 'font-style:bold',
viewConfig: {
plugins: {
ptype: 'treeviewdragdrop',
appendOnly: true
}
}
}
So I have a source tree I can drag from.
The target tree is defined as:
{
xtype: 'treepanel',
flex: 5, iconCls: 'mytreecls',
border: true,
store: emptystore,
rootVisible: false,
title: 'Selected',
bodyStyle: 'font-style:bold',
viewConfig: {
emptyText: '',
plugins: {
ptype: 'treeviewdragdrop',
allowContainerDrop: true,
appendOnly: true
},
listeners: {
drop: function (node, data, model, dropPosition, opts) {
console.log(node);
}
}
}
}
The first problem I have is how can I define an empty treestore with a single root node that will call the proxy url if the data for the node is not loaded.
The source tree will load leaf nodes dynamically, if I drag and add them to the target tree I want to keep that functionality.
I've tried lots of ways to set default root node - none of which I've been able to get working.
var emptystore= Ext.create('Ext.data.TreeStore', {
model: 'TreeModel',
proxy: {
type: 'ajax',
url: '/some_action_that_returns_tree_json',
extraParams: { ... },
reader: {
type: 'json',
root: { text:"My Root",...} // doesn't work, presumably becuase the ajax call overwrite it?
}
}
}
});
The end result should be a source tree that I can drag from into another tree. I don't want to remove the dragged node which I think is controlled by appendOnly property of treeviewdragdrop. I was trying to make it so I could handle the drop on the panel/container by setting allowContainerDrop to true.
To be honest this is my first endeavour into ExtJS D&D so any help appreciated. I've obviously read the tutorial but cannot find my on tree to tree D&D.
Thanks in advance,
Sam
I've configured my store as:
var store = new Ext.data.JsonStore({
url: 'gridData.php',
root: 'movies',
fields: ['film_id', 'title', 'release_year', 'rating']
});
and then defined my grid as:
var grid = new Ext.grid.GridPanel({
title:'Movies',
store: store,
columns: [
{ header: "ID", width: 30, dataIndex: 'film_id',sortable: true, hidden:true },
{ id: 'title-col', header: "Title", width: 180,dataIndex: 'title', sortable: true },
{ header: "Rating", width: 75, dataIndex: 'rating',sortable: true },
{ header: "Year", width: 75, dataIndex: 'release_year',sortable: true, align: 'center' }
],
autoExpandColumn: 'title-col',
renderTo: Ext.getBody(),
width: 600,
height: 300,
loadMask: true
});
then I load the store:
store.load();
I'm doing all this in Ext.onReady method. The data that I want to display is fetched from a php file which is of the following form:
{ "count":2, "movies":[{ "film_id":"1", "title":"ACADEMY DINOSAUR", "description":"An Epic Drama of a Feminist And a Mad Scientist who must Battle a Teacher in The Canadian Rockies", "release_year":"2006", "rating":"PG", "special_features":"Deleted Scenes,Behind the Scenes" }, { "film_id":"2", "title":"ACE GOLDFINGER", "description":"An Astounding Epistle of a Database Administrator And an Explorer who must Find a Car in Ancient China", "release_year":"2006", "rating":"G", "special_features":"Trailers,Deleted Scenes" } ] }
When the page is loaded, the grid keeps showing the loading mask and the data is never shown. Also, I get the error a is undefined. What am I missing?
Edit
I've found that there's some path issue when assigning URL to store but still can't resolve. My "gridData.php" file, JS file and the HTML file where the grid is being displayed, are in the same folder and I'm on "localhost/myapp". Please help!
Your store declares itself to have these fields:
id
title
release_year
rating
However, your JSON data's rows contain these fields:
film_id
title
description
release_year
rating
special_features
Your error is likely caused by the grid looking for an 'id' field that does not exist in the data.
One option is to change your store's field definition to:
['film_id', 'title', 'release_year', 'rating']
You would also need to make a corresponding alteration to the column definition:
{header: "ID", width: 30, dataIndex: 'film_id', sortable: true, hidden: true}
Another option is to add a mapping to the field's definition in the store:
[{name: 'id', mapping: 'film_id'}, 'title', 'release_year', 'rating']
Also, I suggest that while developing you include ExtJS into your page using 'ext-all-debug.js' instead of 'ext-all.js'. The error messages and backtraces in the console will usually be much more descriptive when running against the debug build.
It should be simple. The default value of idProperty is id and you haven't set another. So the store looks for a id field that does not exist.
that should work
var store = new Ext.data.JsonStore({
url: 'gridData.php',
root: 'movies',
idProperty: 'film_id',
fields: ['film_id', 'title', 'release_year', 'rating']
});
Assuming you're running ExtJS 4 define your store like this:
var store = new Ext.data.JsonStore({
proxy: {
url: 'gridData.php',
type: 'ajax',
reader: {
type: 'json',
root: 'movies'
}
},
fields: ['film_id', 'title', 'release_year', 'rating']
});
try with this store:
var store = new Ext.data.JsonStore({
url: 'gridData.php',
root: 'movies',
fields: [
{
name: 'id'
},
{
name: 'title'
},
{
name: 'release_year'
},
{
name: 'rating'
}
]
});