I am trying to set 2 different tool tip message for 2 cells of single column,but on run time single tip message will be applied that is if am clicking on cell with respect to condition of if clause then same tip message will be forwarded to rest of the cells,if i navigate from 1 st cell to 2 cell message will not change 1 st cell message will carry forwards and vise versa if i move from 2nd cell to 1 cell 2nd tip message will remain same for rest of the cells.
celldblclick : function(grid, rowIndex, columnIndex, e) {
var ed = grid.getColumnModel().getCellEditor(columnIndex,rowIndex) || {};
ed = ed.field || {};
if (rowIndex == 0 && columnIndex == 2) {
ed.qtipText="SAMPLE1";
} else {
ed.qtipText="SAMPLE2";
}
}
To get them to display differently I normally attach a function to the tooltip beforeshow method which updates the tooltip before it is displayed:
// add tooltips to grid
myGrid.getView().on('render', function(view) {
view.tip = Ext.create('Ext.tip.ToolTip', {
target: view.el,
delegate: view.itemSelector,
trackMouse: true,
minWidth: 0,
maxWidth: 800,
dismissDelay: 0,
showDelay: 800,
renderTo: Ext.getBody(),
listeners:{
beforeshow: function updateTipBody(tip){
text = view.getRecord(tip.triggerElement).get('tooltip')
tip.setWidth(text.length * 5);
tip.update(text);
}
}
});
});
In the above example I had my tooltips defined for each record in the datastore itself, that is why I call text = view.getRecord(tip.triggerElement).get('tooltip') ('tooltip' is the column in my datastore with the tooltip text). But you could implement whatever logic you want in the beforeshow listener function as long as you call tip.update(yourLogic) at the end.
Related
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.
I have a tabpanel with chats on different tabs. Each tab panel has a chat and the discussions are sometime very long so, in my initComponent, I have a code to continuously scroll to bottom so I can show the latest messages:
setInterval ->
this.scrollBy 100000, 100000
, 100
which works fine for what it's supposed to do. The problem is that I sometimes want to see what I talked earlier and I have to scroll to top but this code obviously wouldn't let me. I implemented a hook:
setInterval ->
if not this.autoscroll_disabled
this.scrollBy 100000, 100000
, 100
and now I just have to catch the event when the user triggers a scroll on my panel so I can set autoscroll_disabled to true until he scrolls back to bottom again probably. Any idea how do I catch a scroll event on a panel in extjs?
Ext.require('*');
Ext.onReady(function () {
var content = [],
i = 1;
for (; i <=100; ++i) {
content.push('Line ' + i);
}
var p = new Ext.panel.Panel({
renderTo: document.body,
width: 200,
height: 200,
autoScroll: true,
title: 'Foo',
html: content.join('<br />')
});
p.getTargetEl().on('scroll', function(e, t) {
var height = p.getTargetEl().getHeight();
if (height + t.scrollTop >= t.scrollHeight) {
console.log('bottom');
}
});
});
I am working with ExtJS 4.2.1
I have a button to make appear a panel.
This panel is containing my treepanel, five checkboxes below, and finally one valid button (to close the treepanel and valid the fact that we checked some nodes) and one cancel button (just to cose the treepanel).
I can make my panel appear and it works fine. But if I click on my cancel or my valid button, the panel will hide (ok), and next time I try to show it it doesn't contain my treepanel anymore, only the five checkboxes and the two buttons (attention, the two panels are different, the panel is containing my treepanel).
I don't understand because there is no reason for it to disappear. When I check the treepanel with some console.log() I can see, passing by treepanel.store.tree.root that my treepanel still exists and is properly filled. When I pass through treepanel.view.all I can see the right elements are present in my view. But when I check treepanel.body.dom with chrome debugging I can't see where the element is (ordinary when you pass over the dom with the mouse on chrome debugging you can see the corresponding part of the page colored).
Here is the concerned part of my code:
var button = Ext.get('ProductSelectionButton');
var treeSelector = createTree('stAddAction.do?action=product_tree_selector', 550, 490, '', 'lbl_st_tree_selection_empty', true, 'productlist');
button.on('click', function(){
treeSelector.store.proxy.url = 'stAddAction.do?action=product_tree_selector';
treeSelector.store.reload();
var productPanel = Ext.create('Ext.FormPanel',{
fieldDefaults:{
labelWidth: 75 // label settings here cascade unless overridden
},
frame:true,
title: document.getElementById('applicability').innerHTML + ' - ' + document.getElementById('lbl_st_product_tree_win').innerHTML,
style:'padding: 5px 5px 0; margin-top: 0;',
width: 550,
items: [treeSelector,
{
xtype: 'checkboxgroup',
items: [
{boxLabel: document.getElementById('lbl_status_deleted').innerHTML, name: 'status_2', checked: false, ctCls:'check-status-2',
listeners: {
change: function(newValue, oldValue, eOpts ){
if(newValue.checked){
// To show items with status 2 which is Deleted status
Ext.Array.remove(statusToHide, "2");
ProductList.showIdsStatus(2);
}
else{
// To hide items with status 2 which is Deleted status
Ext.Array.push(statusToHide, "2");
ProductList.hideIdsStatus(2);
}
}
},
... four others checkboxes
}],
buttons: [{
icon : 'img/st_little_valid.png',
style:'width:20px!important;',
handler: function(){
var data = '',
selNodes = treeSelector.getCheckedNodes(treeSelector.getRootNode());
precedentlyCheckedNodes = selNodes;
xhr = getXhr();
xhr.onreadystatechange = function(){
if (xhr.readyState == 4 && xhr.status == 200) {
var myLoad = eval(myDataGrid);
productgrid.store.loadData(myLoad);
productgrid.getView().refresh();
win.hide();
enableSave();
}
}
var params = "action=set_iceproduct&datatoadd=" + data + "&datatoremove=" + strUnchecked;
xhr.open("POST", "stAddAction.do", true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.setRequestHeader('Content-length', params.length);
xhr.send(params);
}
},
{
icon : 'img/st_little_cancel.png',
handler: function(){
/* restore all nodes how they were before (checked or unchecked) */
treeSelector.verifyCheckedNodes(precedentlyCheckedNodes);
win.hide();
/* Only expand the first level */
treeSelector.collapseAll();
treeSelector.getRootNode().expand();
}
}]
});
I don't know if it really is quite explicit...
Anyway, any idea could be welcomed!
How can this treepanel disappear from my panel and still exist!
Thank you
You are calling Ext.create in the buttons click event function every time. This means that the first time you create it, it's okay. But when you click the button again, it will create another panel with the same configuration, only you can't have treeSelector in both because it is already somewhere else. Change your code to something like:
var button = Ext.get('ProductSelectionButton');
var treeSelector = createTree('stAddAction.do?action=product_tree_selector', 550, 490, '', 'lbl_st_tree_selection_empty', true, 'productlist');
button.on('click', function(button){
treeSelector.store.proxy.url = 'stAddAction.do?action=product_tree_selector';
treeSelector.store.reload();
if(!button.productPanel)
{
button.productPanel = Ext.create('Ext.FormPanel',{
fieldDefaults:{
labelWidth: 75 // label settings here cascade unless overridden
},
frame:true,
title: document.getElementById('applicability').innerHTML + ' - ' + document.getElementById('lbl_st_product_tree_win').innerHTML,
style:'padding: 5px 5px 0; margin-top: 0;',
width: 550,
items: [
treeSelector,
{
xtype: 'checkboxgroup',
items: [
{boxLabel: document.getElementById('lbl_status_deleted').innerHTML, name: 'status_2', checked: false, ctCls:'check-status-2',
listeners: {
change: function(newValue, oldValue, eOpts ){
if(newValue.checked){
// To show items with status 2 which is Deleted status
Ext.Array.remove(statusToHide, "2");
ProductList.showIdsStatus(2);
}
else{
// To hide items with status 2 which is Deleted status
Ext.Array.push(statusToHide, "2");
ProductList.hideIdsStatus(2);
}
}
i have a gridpanel with cellediting plugin, and with a lot of grid header
(at least make the grid shown it horizontal scrollbar)...
here is the DEMO...
there is a bug in my grid, try to edit one of the collumn, and then press tab key to navigate to header15..
the grid didn't scroll to where i am editing,...
is it a bug?? a have looking for this at their forum, but no luck..
so, how to fix it??
how to make my grid scroll to the active editor??
from docs, there is a method scrollByDeltaX,
but how to know the delta from active editor??
Cut it short, try demo first :)
(Too free, and wanted your bounty, please award me!)
Funny that my answer works just nice on 4.0.7, but it doesn't work on 4.0.2a! Out of no clue, I checked the source of 4.0.2a, and shockingly saw this:
In src/panel/Table.js (4.0.2a)
/**
* Scrolls the TablePanel by deltaY
* #param {Number} deltaY
*/
scrollByDeltaY: function(deltaY) {
var verticalScroller = this.getVerticalScroller();
if (verticalScroller) {
verticalScroller.scrollByDeltaY(deltaY);
}
},
/**
* Scrolls the TablePanel by deltaX
* #param {Number} deltaY
*/
scrollByDeltaX: function(deltaX) {
var horizontalScroller = this.getVerticalScroller();
if (horizontalScroller) {
horizontalScroller.scrollByDeltaX(deltaX);
}
},
Noticed anything? Checkout the function scrollByDeltaX! It's coded wrongly (fixed in 4.0.7)!!! And this will obviously wouldn't have any visual feedback. It is asking the vertical scrollbar to do a deltaX scrolling. How can it be?
Anyway, to fix this problem is rather easy, in case you do not want to upgrade to 4.0.7. Afaik 4.0.7 has tons of bugs inherited from 4.0.6, and it breaks my project with that freaking masking issue.
Below is my working answer, and I hope you'll appreciate it. Basically I have modified the onEditorTab method and created an event hook, so your grid can hook onto it, and do the scrollByDeltaX when tabbing is triggered.
I'm not too sure how to do a scroll left most/right most, so a funny Infinity has been used in my code out of laziness.
Here is the example: DEMO (Remember to try out SHIFT+TAB too)
/**
* Customized Row Selection Model which will
* fires "editortab" event when an tabbing occurs
*/
Ext.define('NS.RowModel', {
extend: 'Ext.selection.RowModel',
//False to wrap to next row when you tab
//to the end of a row
preventWrap: false,
initComponent: function() {
/**
* #event editortab
* Fires when editor is tabbed
* #param {RowModel} rowModel this rowmodel
* #param {Editor} edt The editor
* #param {string} dir The direction of the tab (left or right)
* #param {Event} e The event object
*/
this.addEvents('editortab');
this.callParent();
},
//memorizing which is the last context
lastEditorContext: null,
onEditorTab: function(edt, e) {
//Part of this code is from the original onEditorTab in
//src/selection/RowModel.js line 416
var me = this,
view = me.views[0],
record = edt.getActiveRecord(),
header = edt.getActiveColumn(),
position = view.getPosition(record, header),
direction = e.shiftKey ? 'left' : 'right',
newPosition = view.walkCells(position, direction, e, this.preventWrap);
//we store the last context, so we know whether the
//context has changed or not
me.lastEditorContext = edt.context;
//if there is new position, edit; else, complete the edit.
if (newPosition) {
edt.startEditByPosition(newPosition);
}else{
edt.completeEdit();
}
//If context doesn't change, we try to walk
//to the next one until we find a new edit box (context changed)
while (me.lastEditorContext === edt.context && newPosition) {
newPosition = view.walkCells(newPosition, direction, e, this.preventWrap);
if (newPosition) {
edt.startEditByPosition(newPosition);
}
}
//Fires the event
this.fireEvent('editortab', this, edt, direction, e);
}
});
/**
* Customized Editor Grid to support tabbing
*/
Ext.define('NS.EditorGrid', {
extend: 'Ext.grid.Panel',
initComponent: function() {
var me = this;
Ext.applyIf(me, {
plugins: [Ext.create('Ext.grid.plugin.CellEditing', {
clicksToEdit: 1
})],
selModel: Ext.create('NS.RowModel', {
listeners: {
editortab: {
fn: me.onEditorTab,
scope: me
}
}
})
});
me.callParent();
},
onEditorTab: function(sel, edt, dir, e) {
var lastRow = sel.lastEditorContext.rowIdx,
newRow = edt.context.rowIdx,
deltaX = 0;
//Let's calculate deltaX first
//if row changed, we reset the cells to the left most or right most
if (lastRow != newRow) {
deltaX = lastRow < newRow ? -Infinity : Infinity;
}else{
//else, do deltax :)
deltaX = edt.context.column.width * (dir == 'right' ? 1 : -1);
}
//If you are using 4.0.2a, use this. They have typo in
//src/panel/Table.js, line 1133
var horizontalScroller = this.getHorizontalScroller();
if (horizontalScroller) horizontalScroller.scrollByDeltaX(deltaX);
//But if you are running 4.0.7, this is fine. Use this:
//this.scrollByDeltaX(deltaX);
}
});
//-------------------------------------------------
//Everything below remains :)
Ext.onReady(function() {
var storeSr=Ext.create('Ext.data.ArrayStore', {
fields: ["KD_SR","NM_SR"]
});
//load data
var tmpd=[];
for (i=1;i<=15;i++){
tmpd.push([i,"nm "+i]);
}
storeSr.loadData(tmpd);
//create column
col=[]
col.push({header: "Kode", dataIndex: 'KD_SR'});
for (j=1;j<=15;j++){
col.push({
header: "Header"+j,
width:100,
dataIndex: 'NM_SR',
editor:{xtype:"textfield"}
});
}
var gridSr = Ext.create('NS.EditorGrid', {
height: 200,
width: 500,
store: storeSr,
columns: col
});
//create window
var winEditSR=Ext.create("Ext.Window",{
title:"Sub Rayon",
autoWidth : true,
autoHeight : true,
autoShow:true,
border : false,
modal : true,
items : [gridSr]
});
});
I still wondering if there might be a better solution... perhaps using column (header)'s x to determine scroller's scrollLeft, but that will be pretty jerky...
i have an editor grid, what i want to do i create one row in the editor grid that the user have to ADD new information on the grid with blank information.
What i want if, after inserting that row to the editor, apply different style/id/etc to it.
1- How do i do that first?
2- how do i make it that the NEW ROW for inserting is always the last one seen, even after scrolling to another page of that grid ?
Here is the code for assigning a custom class to your new records, and for inserting the new records at the end:
var grid = new Ext.grid.EditorGridPanel({
store: store,
cm: cm,
viewConfig: {
getRowClass : function(record, rowIndex, p, store){
if(record.data.isNew){
return 'x-tab-panel-header';
}
}
},
tbar: [{
text: 'Add New',
handler: function() {
var Rec = grid.getStore().recordType;
var p = new Rec({
col1: 'value1',
col2: 1.01
});
grid.stopEditing();
var newRow = store.getCount();
p.data.isNew = true;
store.insert(newRow, p);
grid.startEditing(newRow, 0);
}}]
});
You can test this sample here: http://jsfiddle.net/xjkB5/