ExtJS 4.1.1: Working with a TreeGrid/TreeStore - extjs

I am having some problems with my code that I hoped you could help me with as I've kind of hit a wall.
I have a field in a Tree grid that has the following properties:
xtype : 'gridcolumn',
id : 'raGridFormulaLink_Purchased',
dataIndex: 'formulaLink',
groupable : false,
editor : {
xtype: 'textfield'
},
renderer: function(value, metaData, record, rowIndex, colIndex, store) {
var rVal; var linkRec;
if(value !== '' && value !== 0) {
/* TODO Find linked Record based on ['child_id' => value]
* and print that record's [text] to rVal */
rVal = Ext.local.langstore[448] + ' ' + value;
}
return rVal;
},
align: 'left',
width: 100
As you can see I am trying to do a simple HLOOKUP to find the linked record. But I am unable to get the proper record from the store. How can I do this?
The value has the right "child_id", so it's not the input that's wrong.
Any help appreciated,
GR.

Solved it.
Final code:
renderer: function(value, metaData, record, rowIndex, colIndex, store) {
var rVal; var rText = ''; var node;
if(value !== '' && value !== 0) {
if(record.isLeaf()) {
var node = record.parentNode.findChild('child_id',value);
rText = node.data.text;
rVal = Ext.local.langstore[448] + ' ' + rText;
}
}
return rVal;
},

Related

How can I retrieve the cursor position in an ExtJS text area field?

I defined a text area field in an extJS window as follows:
me.myTextArea = Ext.create({
xtype: 'textareafield',
width: 500,
height: 500,
editable: true,
selectOnFocus: false,
listeners: {
afterrender: function() {
this.focus(true);
let cursorPos = this.getValue().length;
this.selectText(cursorPos, cursorPos);
}
}
});
I added the text area field to a panel contained within a window, and I set the text area field as focus element. I prevented the text there to be selected after the textarea field's being rendered. I would like to add the following feature. On closing the window, I will be able to get the position the cursor has within the text area field. So far, my attemps at resolving the problem were withou success. I set up an alert as follows:
listeners: {
'close': function(me) {
alert(me.getCaretPos(cmp.myTextArea.getEl().getId()));
}
},
Now the function named "getCaretPos" is designed to get the cursor position. I did not invent the function, but I found in on the net. Haplessly, the function does not work, it always returns -1:
getCaretPos: function(id){
var el = document.getElementById(id);
var rng, ii=-1;
if(typeof el.selectionStart=="number") {
ii=el.selectionStart;
} else if (document.selection && el.createTextRange){
rng=document.selection.createRange();
rng.collapse(true);
rng.moveStart("character", -el.value.length);
ii=rng.text.length;
}
return ii;
}
Especially, I do not undertsand, why "el.selectionStart" is always undefined in the function. I would be very glad if somebody could help me in resolving this mystery.
In this FIDDLE, I have created a custometextarea using extend:Ext.form.field.TextArea and putted some custom method. I hope this will help/guide you to achieve your requirements.
I have checked this code is working in ExtJS 4.x and later.
CODE SNIPPET
Ext.application({
name: 'Fiddle',
launch: function () {
Ext.define('CustomeTextArea', {
extend: 'Ext.form.field.TextArea',
xtype: 'customtextarea',
inputTypeSelectionSupported: /text|password|search|tel|url/i,
selectDir: {
b: 'backward',
back: 'backward',
f: 'forward'
},
/*
* this event will call get the cursoe postion inside of field
* #return {NUMBER}
*/
getCaretPos: function () {
var dom = this.inputEl.dom,
pos, selection;
if (this.inputTypeSelectionSupported.test(dom.type)) {
pos = dom.selectionStart;
selection = (typeof pos !== 'number') && this.getTextSelection();
if (selection) {
pos = selection[0];
}
} else {
Ext.raise('Input type of "' + dom.type + '" does not support selectionStart');
}
return pos;
},
/*
* this event will call selectText event
* #params {NUMBER} pos
*/
setCaretPos: function (pos) {
this.selectText(pos, pos);
},
/*
* #params {NUMBER} start
* #params {NUMBER} end
* #params {STRING} direction to select it is optional
*/
selectText: function (start, end, direction) {
var me = this,
range,
dom = me.inputEl.dom,
len;
if (dom && me.inputTypeSelectionSupported.test(dom.type)) {
start = start || 0;
len = dom.value.length;
if (end === undefined) {
end = len;
}
direction = me.selectDir[direction] || direction || 'forward';
if (dom.setSelectionRange) {
dom.setSelectionRange(start, end, direction);
} else if (dom.createTextRange) {
range = dom.createTextRange();
range.moveStart('character', start);
range.moveEnd('character', -(len - end));
range.select();
}
} else if (!me.inputTypeSelectionSupported.test(dom.type)) {
Ext.raise('Input type of "' + dom.type + '" does not support setSelectionRange');
}
return me;
},
//This event will select the text inside of textfield/textarea
getTextSelection: function () {
var dom = this.inputEl.dom;
if (this.inputTypeSelectionSupported.test(dom.type)) {
return [
dom.selectionStart,
dom.selectionEnd,
dom.selectionDirection
];
} else {
Ext.raise('Input type of "' + this.dom.type + '" does not support selectionStart, selectionEnd and selectionDirection');
return [];
}
}
});
Ext.create('Ext.window.Window', {
title: 'cursor position',
height: 200,
width: 400,
layout: 'fit',
items: [{
xtype: 'customtextarea',
margin: 5,
grow: true,
name: 'message',
fieldLabel: 'Message',
labelAlign: 'top',
value: 'How can I retrieve the cursor position in an ExtJS text area field?',
anchor: '100%',
listeners: {
afterrender: function (cmp) {
Ext.defer(function () {
cmp.focus(false); //if you pass true then it will automatically select text inside of field
let cursorPos = cmp.getValue().length;
cmp.selectText(0, cursorPos - 5, 'b');
}, 50)
}
}
}],
listeners: {
beforeclose: function (win) {
var textArea = win.down('customtextarea'),
pos = textArea.getCaretPos();
Ext.Msg.alert('Success', `This is your cursor postion <b>${pos}</b>`)
}
}
}).show();
}
});

ExtJS Change actioncolumn icon from controller / handler

TLDR: I'm using ExtJS 4 and I want to change action column buttons icon from hanlder / controller. How I can do it?
My problem: I have a menu to create a group of devices, it cointain a table of all existing devices (the device has an id, name and affiliation to the group member) with pagination and ajax store. To create a group I have to pass an array of device ids to the server.
To do this I add action column to my grid. By clicking on button in action column I want to add device id to one of the two arrays, that are stored as attributes of the grid (addedMembers and deletedMembers) and change icon in action column. At the moment, all the following code works, but I do not understand how I can change the icon?
Grid:
Ext.define('Portal.view.devicegroups.GroupDevicesGrid', {
extend: 'Ext.grid.Panel',
alias: 'widget.groupDevicesGrid',
addedMembers: [],
deletedMembers: [],
store: 'devicegroups.GroupDevicesStore',
columns: [
{
dataIndex: 'name',
flex: 1,
sortable: true,
text: Ext.String.capitalize("<?=gettext('name')?>")
},
{
xtype: 'actioncolumn',
text: Ext.String.capitalize("<?=gettext('member')?>"),
width: 75,
items: [
{
getClass: function (value, meta, record, rowIndex, colIndex) {
var cls = 'deny';
if (this.up('groupDevicesGrid').deletedMembers.indexOf(record.get('id')) !== -1 || record.get('member') == 1) {
cls = 'allow';
}
return cls;
},
handler: function (view, rowIndex, colIndex, item, event, record, row) {
this.fireEvent('changeMembership', rowIndex, record);
}
}
]
}
]
});
changeMembership method:
changeGroupDeviceMembership: function(rowIndex, device) {
var groupDevicesGrid = this.getGroupDevicesGrid(),
groupDevicesStore = groupDevicesGrid.getStore(),
addedMembers = groupDevicesGrid.addedMembers,
deletedMembers = groupDevicesGrid.deletedMembers,
deviceId = device.get('id'),
isMember = device.get('member');
if(isMember == 1) {
if(deviceId) {
if(deletedMembers.indexOf(deviceId) === -1) {
// Set allow icon
deletedMembers.push(deviceId);
} else {
// Set deny icon
deletedMembers.splice(deletedMembers.indexOf(deviceId), 1);
}
}
} else if(isMember == 0) {
if(deviceId) {
if(addedMembers.indexOf(deviceId) === -1) {
// Set deny icon
addedMembers.push(deviceId);
} else {
// Set allow icon
addedMembers.splice(deletedMembers.indexOf(deviceId), 1);
}
}
}
},
Or perhaps there is a better solution to my problem?
I am not privileged to comment so I will just take a shot at the answer. This is the way I do it..you are nearly there just add iconCls. :)
{
xtype: 'actioncolumn',
text: Ext.String.capitalize("<?=gettext('member')?>"),
width: 75,
items: [
{
iconCls:'deny', //<== try adding this icon cls
getClass: function (value, meta, record, rowIndex, colIndex) {
var cls = 'deny';
meta.tdAttr = 'data-qtip="Deny"'; //<== I like tool tips
if (this.up('groupDevicesGrid').deletedMembers.indexOf(record.get('id')) !== -1 || record.get('member') == 1) {
cls = 'allow';
meta.tdAttr = 'data-qtip="Allow"'; //<== I like tool tips
}
return cls;
},
handler: function (view, rowIndex, colIndex, item, event, record, row) {
this.fireEvent('changeMembership', rowIndex, record);
}
}
]
}
I use this pattern quite a lot, hopefully it works for you too.

Tooltips overriding column display data in EXT JS 5

I have a column grid issue where I want to take the data of a grid cell truncate it down to 50 characters and then have a tooltip show the full data.
I have the SQL service responding back with the truncated text called OfferTruncated and the full text called Offer in the model/store. What's happening is all I am trying to display is OfferTruncated on the grid and Offer in the tooltip, but Offer is displayed in both.
Here is the column item
{
header: 'Offer',
dataIndex: 'Offer',
width: 300,
renderer: function (value, metadata, record) {
return getExpandableImage(value, metadata, record);
}
},
Here is the global function I made
function getExpandableImage(val, meta, rec, rowIndex, colIndex, store) {
var deviceDetail = "Offer Terms: " + rec.get('Offer');
meta.tdAttr = 'data-qtip="' + deviceDetail + '"';
var value = rec.get('OfferTruncated')
return value;
}
It's a little easier to just use the built in EXTjs ellipsis function, rather than returning two fields where one is just truncated data of the other. Use the renderer:
{
header: 'Offer',
dataIndex: 'Offer',
width: 300,
renderer: function (value, metadata, record) {
var deviceDetail = "Offer Terms: " + value;
metadata.tdAttr = 'title="' + Ext.util.Format.ellipsis(deviceDetail, 800) + '"';
return Ext.util.Format.ellipsis(value, 50);
}
},

Get Values Of Columns Not Associated to store Extjs4

I have a gridpanel with columns associated to its store (with "dataIndex") and columns not associated to store (without "dataIndex" ) for example:
{
xtype: 'gridcolumn',
renderer: function(value, metaData, record, rowIndex, colIndex, store, view) {
var data=record.getData(true);
if(data.currProbability!==undefined){
if(data.currProbability<5)
return 'L';
else
if((data.currProbability>4)&&(data.currProbability<7))
return 'M';
else return 'H';
}else
return "";
},
text: 'Probability'
},
{
xtype: 'gridcolumn',
renderer: function(value, metaData, record, rowIndex, colIndex, store, view) {
var data=record.getData(true);
if(data.currSeverity!==undefined){
if(data.currSeverity>8)
return 'C';
else
if((data.currSeverity>6)&&(data.Severity<9))
return 'S';
else
if((data.currSeverity>4)&&(data.currSeverity<7))
return 'M';
else
return 'L';
}
return "";
},
text: 'Severity'
}
for these two columns I haven't problem with renderer But the third column:
{
xtype: 'gridcolumn',
renderer: function(value, metaData, record, rowIndex, colIndex, store, view) {
var row=view.getNode(rowIndex);
var data=record.getData(true);
if(row !==undefined){
var severity=Ext.fly(Ext.fly(row).query('.x-grid-cell')[25]).down('div').getHTML();
var probability= Ext.fly(Ext.fly(row).query('.x-grid-cell')[24]).down('div').getHTML();
if(data.status==='Closed')
return severity+probability+'c';
else
return severity+probability;
}
return "";
},
text: 'Risk Class'
}
with this column in its renderer I can't get the value of two later columns ("probability" and "severity") I understood this problem because I get values not from record but from two later columns not associated in the store here like a summury column, In the renderer for this column 'Risk Class' the variable row is indefined.
please how I can resolve it.
Thanx.
Use a calculated field on your model.
fields: [{
name: 'severity',
convert: function(v, record) {
var severity = record.get('currSeverity');
if (severity) {
if (severity > 8) {
return 'C';
}
// etc
}
return '';
}
}]
Then you can use it as a dataIndex directly in your grid. You can also ask the model for the value:
record.get('severity');

How can I add row numbers to an ExtJS grid?

In an ExtJS GridPanel, is there a way to design a column whose sole purpose is to act as a serial number column? This column will not need a dataIndex property.
Right now, I am using a custom row numberer function, but this means the row numberer is defined in the grid.js file and all columns from grid.ui.js needs to be copied into grid.js.
I am using the Ext designer.
EDIT: The crux of my question is: Is there a way to define a row numberer using the Ext designer?
All you need is an Ext.grid.RowNumberer in your column definition.
var colModel = new Ext.grid.ColumnModel([
new Ext.grid.RowNumberer(),
{header: "Name", width: 80, sortable: true},
{header: "Code", width: 50, sortable: true},
{header: "Description", width: 200, sortable: true}
]);
Not an answer, but just want to share this:-
On top of the Ext.grid.RowNumberer, you can have this small nifty hack which will increments your numbers correctly according to the page number that you are viewing if you have implemented PagingToolbar in your grid.
Below is my working example. I extended the original Ext.grid.RowNumberer to avoid confliction.
Kore.ux.grid.RowNumberer = Ext.extend(Ext.grid.RowNumberer, {
renderer: function(v, p, record, rowIndex) {
if (this.rowspan) {
p.cellAttr = 'rowspan="'+this.rowspan+'"';
}
var st = record.store;
if (st.lastOptions.params && st.lastOptions.params.start != undefined && st.lastOptions.params.limit != undefined) {
var page = Math.floor(st.lastOptions.params.start/st.lastOptions.params.limit);
var limit = st.lastOptions.params.limit;
return limit*page + rowIndex+1;
}else{
return rowIndex+1;
}
}
});
And the code below is the original renderer from Ext.grid.RowNumberer, which, to me, pretty ugly because the numbers is fixed all the time no matter what page number it is.
renderer : function(v, p, record, rowIndex){
if(this.rowspan){
p.cellAttr = 'rowspan="'+this.rowspan+'"';
}
return rowIndex+1;
}
For version 4.2 very very easy:
Just add a new column like this:
{
xtype: 'rownumberer',
width: 40,
sortable: false,
locked: true
}
ExtJS 4.2.1 working code below:
// Row numberer correct increasing
Ext.override(Ext.grid.RowNumberer, {
renderer: function(v, p, record, rowIndex) {
if (this.rowspan) {
p.cellAttr = 'rowspan="'+this.rowspan+'"';
}
var st = record.store;
if (st.lastOptions.page != undefined && st.lastOptions.start != undefined && st.lastOptions.limit != undefined) {
var page = st.lastOptions.page - 1;
var limit = st.lastOptions.limit;
return limit*page + rowIndex+1;
} else {
return rowIndex+1;
}
}
});

Resources