I have 10 grids in my project where I want to define one extra header, and that header will open menu on double click, single click will return null. This functionality works fine in my 3.4 version. But somehow i am not able to extend 'Ext.grid.header.container' class. Any suggestion why?? Please refer below my code.
Ext.define('Ext.grid.HeaderColumnModel', {
extend: 'Ext.grid.header.container',
initComponent: function()
{
this.callParent();
}
}
Usage
columns : new Ext.grid.HeaderColumnModel()
OR
colModel: new Ext.grid.HeaderColumnModel()
Related
My combo uses remote query. When the user types something, the server returns matching results. However, when there are a lot of matching results, then the combo expands, loses focus and highlights the firts record returned by the server. The combo has these properties:
...
queryMode:'remote',
enableKeyEvents:true,
forceSelection:true,
...
The screen of what is going on is here:
So, as you can see, when the user typed the last character, the server returned records and for some (I think stupid) reason highlighted the first record. But what is more important there is no focus any longer and the user has to put cursor on the field again to continue typing. To solve this problem, I tried these events:
'blur':function(){
this.focus();
},
'keydown':function(){
this.focus();
},
'keypress':function(){
this.focus();
},
'keyup':function(){
this.focus();
},
But there is no effect. I also tried to use load event, but it also has no effect.
I had this issue too, for solve it use the afterQuery property in the combo.
Something like this:
afterQuery: function() {
combo.setRawValue(combo.lastQuery);
},
pd: I think this is a Bug, but i'm not sure about it...
I could solve the similar issue with focus be two actions:
Set "selectOnFocus: false"
Update doRawQuery.
doRawQuery: function() {
var me = this;
...
me.inputEl.focus();
}
If you have your overridden version (I believe you should to not change original plugin), you can do it this way to not duplicate the logic:
doRawQuery: function() {
var me = this;
me.callParent(arguments);
me.inputEl.focus();
}
xtype: 'combo',
...
listeners:{
// repair raw value after blur
blur:function() {
var val = this.getRawValue();
this.setRawValue.defer(1, this, [val]);
}
}
Look this example(thanks to Saki)
I have a sencha touch 2.3 app that has a list which is grouped-
grouped: true,
The grouper function is defined in the store -
grouper: {
groupFn: function(record) {
return record.get('name');
}
}
All this works fine. Now, during runtime, I want to update the grouper function, eg: group it by some other record attribute like location
How do I do this dynamically?
I plan to update the grouper function when the user taps a button (eg: User wants to see the list of records grouped by location)
How to achieve this?
I believe you can use the setGrouper method provided by the Store class : http://docs.sencha.com/touch/2.3.2/#!/api/Ext.data.Store-method-setGrouper
You just need specify your gouper again :
yourStore.setGrouper({
groupFn : function(record) {
return record.get('location');
}
});
You may have to refresh your list manually, as I don't think there is an event that is fired by this change, and that is caught by the List to repaint.
I need to get(retrieve) updated cell value in controller. (MVC)
So I tried this,
var modified = this.getItemGrid().getStore().getUpdatedRecords();
console.log(modified); // return [] empty array
var modified = this.getItemList_Store().getUpdatedRecords();
console.log(modified); // return [] empty array
but always it returns empty array even I updated some cell value.
anybody know what I am doing wrong?
Here is my part of view code,
Ext.define("App.view.orders.ItemList_view", {
extend: "Ext.grid.Panel",
alias: "widget.itemList_view",
plugins: [
Ext.create('Ext.grid.plugin.CellEditing', {
clicksToEdit: 1
})
],
initComponent: function () {
this.store = "ItemList_store";
this.columns = [
{
xtype: 'checkcolumn', text: "Ship", width: 50, dataIndex: "DR"
},
{ header: "test", width: 100, dataIndex: "test",
editor: {
xtype : 'textfield'
}
}
];
this.selModel = Ext.create("Ext.selection.CheckboxModel");
//this.selModel = Ext.create("Ext.selection.CellModel"); // It does not works either.
this.callParent(arguments);
},
.
.
.
Thank you!
[EDIT]
Thank you very much for your answer! I have some more question about editor grid.
Its much different from Ext3. so I'm very confusing now :(
Q1. How to collect edited record data (once click button)?
the event fired once the grid cell be changed.
but I want collect edited grid record once I click the 'Update edited cell' button, and I want to update all together at the once.
In Ext3, I did like this,
(button) click : function(){
var modified = mygridStore.getModifiedRecords();
var recordsToSend = [];
Ext.each(modified, function(record){
recordsToSend.push(record.data);
});
var grid = Ext.getCmp('grid');
grid.el.mask('Updating','x-mask-loading');
grid.stopEditing();
recordsToSend = Ext.encode(recordsToSend);
Ext.Ajax.request({
url : '/test/test',
params : {
data : recordsToSend
},
success : function(response){
grid.el.unmask();
alert(response.responseText);
mygridStore.commitChanges();
},
failure : function(response){
mygridStore.rejectChanges();
}
});
}
How can I change the code for Extjs4 ?
Q2. I don't know still how to find out for changed checkcolumn.
I tried this, but I does not work for checkcolumn (of cause I tested after change checkbox)
// grid coumn
{
xtype: 'checkcolumn', header: "My Check Column", width: 50, dataIndex: "CH"
}
-
// in control
'myGrid': {
validateedit: function (plugin, edit) {
console.log(edit);
},
checkchange: function (plugin, edit) {
console.log(edit);
console.log(edit.value);
}
}
Q3. When I click the cell to edit, the show some HTML tag in -_-;;
I really appreciate for your help. and thank you very much for your valuable time!
The editors (cell editors or row editors) do not commit their values to the store until you complete the edit - which means pressing ENTER or blurring the active cell editor by clicking elsewhere on the page, or clicking the save button on the row editor form .
If your purpose for reading the updated value in your editor is to perform some kind of validation I would suggest simply listening to the validateedit event in your grid's controller, as described here.
The second argument that this event passes to your handler contains a lot of data about the edit that you can then perform validation with. If the edit doesn't pass your validation you can return false from your handler and the value in the celleditor will revert to it's original value. The validateedit event gets fired from the editor grid itself so you would add an event handler in your controller for it like this:
Ext.define('MyApp.controller.MyController', {
init: function() {
this.control({
'mygridpanel': {
validateedit: function(plugin, edit) {
// silly validation function
if (edit.value != 'A Valid Value') {
return false;
}
},
},
});
},
});
But you should check out the link above to see all the different objects available in that second argument I named edit.
The validateedit event is fired right before the record is committed into the store - after the user has already clicked ENTER or blurred the editor, i.e., while the editor is closing.
If you are trying to get the celleditor's value before it starts to close, for some reason other than validation for example, you could get the active celleditor's value like this:
// myGrid is a reference to your Ext.grid.Panel instance
if (myGrid.editingPlugin.editing) {
var value = myGrid.editingPlugin.getActiveEditor().field.value
console.log('value: ' + value);
}
If there is no active editor then myGrid.editingPlugin.getActiveEditor().field would throw an error, that's why I wrapped a conditional around it.
One other point I should make, for validation in editor grids, I found that it is easiest to just put a validator config in the grid column's editor definition. That will give you all the handy validation CSS while the user is setting the field's value and alert him if there is a problem with the value before he tries to save it.
To get an idea of what I mean, try entering letters in the date column of this example. Mouse over the editor cell and you will get the error message.
EDIT
It seems I misunderstood you original question, I'll break down my answers to your questions above though,
Question 1
Once you have completed an edit (clicked ENTER or ), your call to mygridStore.getModifiedRecords() should be working fine because the record will have been committed to the store. I see that it was not working, I will cover that in a moment.
I should point out that ExtJS4 has a store.sync() method as covered here.
Instead of extracting the modified records from the store, encoding them, manually doing an ajax request to save them to the server and then manually committing them you can call this sync method and it will take care of all of these actions for you.
If you have different URLs to handle the different create, read, update, destroy operations fired off by your store's load and sync methods, you can use the store's proxy api config to map your URLs to these operations as covered here. Or you can set-up your server side controller to be able to differentiate between your store's load request (read operations default to HTTP GET) and it's sync requests (create, update and delete operations default as HTTP POST).
There could be many different ways to go about doing this on the server side, the way I usually do it is to have one SQL stored procedure for GET requests and one for POST requests for any given store. I include the store name as an extra param and then my server side controller runs the appropriate stored procedure based on whether it is a GET or a POST request.
Question 2
Cell editing doesn't support checkcolumn edits. You have to make a different handler to listen to changes on that, something like this:
checkchange: function (column, rowIndex, checked) {
var record = store.getAt(rowIndex),
state = checked ? 'checked' : 'unchecked'
console.log('The record:');
console.log(record)
console.log('Column: ' + column.dataIndex);
console.log('was just ' + state)
}
Your call to mygridStore.getModifiedRecords() should be able to pick up the check changes also however, they get committed to the grid's store right away after being checked. store.sync() would also pick up changes to checkcolumn.
Question 3
I can't completely tell what is causing that problem but it may be something strange going on with your validateedit event, your handler should be returning true or false.
As I said earlier, I misunderstood the reason you originally asked this question. I thought you were trying to do some kind of validation while an edit was in progress. Now I understand that you are trying to get all of the modified records from the store after all the editing is completed in order to save them to the database, I was thrown off because in ExtJS 4 a store is usually saved to the database with the sync method as I mentioned.
In other words, you don't need the validateedit event or checkchange event to get a list of modified records.
The actual problem you are having might be trouble with the store's getter methods (getModifiedRecords, getUpdatedRecords) in some 4.07 versions, take a look at this post and this one.
So with all that said, the best advice I can give you is 1) try out the stores sync method for saving modified data to the database and 2) upgrade to ExtJS 4.1, there were a lot of bugs that were straightened out between 4.07 and 4.1 which you should be able to take advantage of, I cut out about 75% of the overrides I was using to make things work when I switched over to 4.1.
EditedGrid.plugins[0].completeEdit();
This will make the active changes commit and call edit event also.
listeners: {
validateedit: function (editor, e) {
//console.log(editor);
var oldVal = editor.originalValue;
var newVal = editor.value;
}
}
I'm new to ExtJS 4 and need some help understanding how the Ext.define works, please.
In fact what I want to do is something similar to the portlets in the portal example, in my application I will need so many objects to add in my different tabs, so in order to organize my code and not have just one very big script, I want to define each component I need in a separate file and then call it in the main script when I need it (I will mainly use the examples so this is why I want to know how Ext.define works so I can adapt those examples and make them work the way I want).
I hope I was clear.
And thank you in advance for your help.
Ext.define ( String className, Object data, Function createdFn ) : Ext.Base
Ext.define is used to define a class. Example:
// creates My.computer.NoteBook Class
Ext.define('My.computer.NoteBook', {
extend:'Ext.panel.Panel',
config: {
hardware:'Dell',
os:'Linux',
price:500
},
constructor:function(config) {
this.initConfig(config);
return this;
}
});
// creates instance of My.computer.NoteBook Class
var myComputer = Ext.create('My.computer.NoteBook', {
hardware:'MacBook Pro',
os:'Mac OS X',
price:1800
});
so, with Ext.define you make a mold, witch you can use later in many cases. You can define width, height, id, css, so later you just call that mold/class. In your case you can define a class for every tab, and then when you make a function to open/create that tab you can say:
if(existingTab){
mainPanel.setActiveTab(existingTab);
}else{
mainPanel.add(Ext.create('My.computer.NoteBook', {id:tabId})).show();
}
...
You can put every Class in your separate .js file, later, on production you will make a class.js with all classes in one minified .js file!
You can define a class and then say:
items: Ext.create("My.computer.NoteBook",{
...
})
Ext JS 4 has a new way to extend... it's call Ext.define and it incorporates Ext.extend, Ext.reg and Ext.ns that we had to do in Ext JS 3 and before into one method call...
Ext.define('com.sencha.MyPanel', {
extend : 'Ext.panel.Panel',
alias : 'widget.mypanel',
...
...
});
Ext.define takes two params, first is the full class name (will act as Ext.ns to create the path and will create the Object) and the config. In the config you specify what class you are extending using the extend config. You set up an XType using the alias config. The alias config is a little different as it has two parts... first part is the type (widget in this case) and then the XType (mypanel).
I want to show only one GridPanel,which I dynamically add by switch click button event, in window.
var event_menu = new Ext.menu.Menu( {
id : "event_menu",
items : [ {
text : 'record1',
handler : function() {
win.add(item_list_panel);//dynamica add GridPanel to show server data
win.doLayout();
item_list_store.load();
}
}, {
text : 'record2',
handler : function() {
win.remove(item_list_panel);//I want to remove it inorder to show the item_list_panel2 and only show one panel.
win.add(item_list_panel2);
win.doLayout();
item_list_store.load();
}
} ]
});
and this menu belong to my window tbar.
when I click record win will show item_list_panel and I want to when I click record2 the item_list_panel2 will show in win and item_list_panel will hide.
If I win.remove(item_list_panel) will have an error :
c.getPositionEl().dom is undefined
How can I do it,Thanks
I can barely understand your question, but if I understand correctly you can do it several ways.
you can destroy the component directly
item_list_panel.destroy()
you can go through your items and select it by id
win.items.item('item_id').destroy()
There are also ways to remove it without completely destroying it, depends what you want to do