I'm trying to use renderer config inside Ext.column. I have two fields states in Model; balanceok and lastbalance. But it gives this error:
[W] XTemplate evaluation exception: getRecord is not defined
How I can display another field with get method?
Model:
Ext.define('MultiDB.model.FolioModel', {
extend: 'Ext.data.Model',
fields: [
{name: 'clientname', type: 'string'},
{name: 'balanceok', type: 'bool'},
{name: 'lastbalance', type: 'int'}
]
Grid Panel:
{
dataIndex: 'balanceok',
flex: 1,
text: 'Balance',
renderer: function (value, record, store) {
if (value == 1) {
return "All Paid";
} else {
return getRecord('lastbalance');
}
}
}
Renderer already provides a record argument. You can use getRecord when focusing on a grid cell, but it looks like you do not need this from the use case described above.
It looks like you have the renderer arguments a little off, which may be why you are having an issue checking and retrieving the value.
If you update your column renderer from:
renderer: function (value, record, store) { ... }
to:
renderer: function (value, metaData, record, rowIndex, colIndex, store, view) { ... }
You can see a full description of render method here:
http://docs.sencha.com/extjs/5.1.1/api/Ext.grid.column.Column.html#cfg-renderer
Take a look at the fiddle below for a working example that will help get you going:
https://fiddle.sencha.com/#view/editor&fiddle/251r
Not sure where you found getRecord, the correct call would be:
record.get('lastbalance');
As a side note, the check for value == 1 is a little odd since the field will be casted to a boolean because of the model.
Related
More or less the configuration looks like this:
{
xtype: 'widgetcolumn',
//text: "", //localize
dataIndex: "carStatusButton",
//disable action for the column
sortable: false,
filter: false,
menuDisabled: true,
widget: {
xtype: 'changeavailbutton',
//reference: "gridCarStatusButton", we cannot use reference because we get a duplicate reference warning
//text is being automatically generated from dataIndex of widgetcolumn
/*
//didn't work!
defaultBindProperty: "curCarStatus", //default is text
curCarStatus: "aaaaaaaa",
setCurCarStatus: function (value) {
this.curCarStatus = value;
},*/
/*
getCurCarStatus: function () {
return "aaaaaa"
},
setCurCarStatus: function (value) {
},*/
/*text: (function() {
return this.enableToggle;
})(),
bind: {
},*/
},
}
We have considered using the updater(cell, value, record, view) but it does not get called initially
We have considered using the renderer(value, metadata, record) but we can only affect the value, it does not give us any help with the widget
We considered to use a custom defaultBindProperty in the widget like this:
defaultBindProperty: "curCarStatus", //default is text
curCarStatus: "",
setCurCarStatus: function (value) {
this.curCarStatus = value;
}
The above helped to avoid creating an extra field in the model that would be necessary. In other words initially we had a field in the model, as a transient field to get the calculated value inside the dataIndex of the widgetcolumn but didn't bring any help on what we were trying to achieve.
The fact is that (from documentation) widgetcolumn binds the dataIndex to the defaultBindProperty of the widget. One problem is that there is a bind that happens in the background that we are not aware of its key value. It would look like that if it was a configuration:
bind: {
text: "{unknownProperty}"
}
If we knew how the property was called it could be helpful to use it in various properties because in our situation we need to bind more than one properties to the widget.
We are actually looking similar functionality provided by isDisabled provides to an ActionColumn to have it in a WidgetColumn.
In the widgetcolumn itself:
onWidgetAttach: function (column, widget) {
if (widget.getWidgetRecord().get('property')) {
widget.setDisabled(false)
} else {
widget.setDisabled(true)
}
}
And the grid can be updated with grid.getView().refresh() to reflect any changes
I have in my ExtJS 4.2.1 Application a grid with the following editable column:
text: 'Location',
dataIndex: 'LocationId',
width: 140,
renderer: function(value) {
var record = me.store.findRecord('LocationId', value);
return record.get('Description');
},
editor: {
xtype: 'combobox',
typeAhead: true,
triggerAction: 'all',
store: Ext.create('App.store.catalog.Location', {
autoLoad: true
}),
displayField: 'Description',
valueField: 'LocationId',
listConfig: {
width: 250,
loadingText: 'Searching...',
// Custom rendering template for each item
getInnerTpl: function() {
return '<b>{Code}</b><br/>(<span style="font-size:0.8em;">{Description}</span>)';
}
}
}
The combo has a renderer to display the Description of the LocationId selected.
Then, my grid has the feature 'Ext.grid.plugin.CellEditing' so I can edit just that column cell.
The problem that I have is when I press the "Update" button, the combo display value returns to the original it used to have, even if the LocationId in the record has the right value.
This is my code that gets fired when the user press the "Update" button.
me.rowEditing = Ext.create('Ext.grid.plugin.RowEditing', {
clicksToMoveEditor: 1,
autoCancel: false,
listeners: {
edit: function(editor, e) {
var record = e.record;
me.setLoading('Updating...');
App.util.Ajax.request({
noMask: true,
url: '/api/catalog/UpdateEmployeeLocation',
jsonData: record.getData(),
success: function(response, opts) {
var obj = Ext.decode(response.responseText);
if (obj.success) {
// commit changes (no save just clear the dirty icon)
me.getStore().commitChanges();
}
},
callback: function() {
me.setLoading(false);
}
});
}
}
});
The record is saved correctly in my database but the combo display value is not updated with the description that corresponds to the LocationId. If I reload the store from server again then It shows correctly.
So, there is something wrong with the renderer in my column that is not updating the value after I update my record.
Any clue on how to get around this?
Thanks.
You are setting dataIndex as 'LocationId' but no where you are changing the 'LocationId', you are just changing description and updating it in rendered method. Since there no change in 'LocationId', store doesn't consider it as dirty field and hence rendered function is not getting called. One quick and dirty way could be instead of using 'LocationId', create another field in the model say 'LocationIdchangeTraker'. Use 'LocationIdchangeTraker' instead of 'LocationId' in data index. It doesn't not effect your view because you are changing the value in reneerer function. Now whenever you update the function change the value of 'LocationIdchangeTraker' as shown below.
record.set('LocationIdchangeTraker',Ext.getId());
I have a Grid-Panel with a few columns.
Now I want to set a new Class in a Column of a Row, when the values don't match with each other.
But how can i get success to a column in a different row?
Her is my code which I tried, but it says, the ID is undefined:
...{
header: 'CRS',
dataIndex: 'crs',
id:'crs',
flex:1,
renderer: function(value, meta) {
console.log("csv-->"+Ext.getCmp('csv').value);
if(value==Ext.getCmp('csv').value)
{
//change class
}
}
},
{
header: 'CSV',
dataIndex: 'csv',
id:'csv',
flex:1
},...
The code you've posted does not seem to match what you're asking for. According to your code, it appears that you're trying to compare values across columns in the same row, not a different row. So which is it?
Anyway, assuming that your code is indicative of what you want, be sure to look at the docs for the the renderer: http://docs.sencha.com/extjs/4.2.1/#!/api/Ext.grid.column.Column-cfg-renderer
One of the arguments passed to the renderer method is the "record", which will contain all the values for the record which is filling the values for the entire row. If you wanted to compare values across columns, you could do something like:
if( value==record.get( 'csv ') ) {
...do something here...
}
If you really need to compare values across rows, then the "store" also gets passed as one of the arguments to renderer, so you could compare values against specific row values that way.
Alternatively, you could do most of this in Model itself. If you are just comparing columns in the same row, you could create an additional field in your Model that stores the result of the comparison. If you did that, all that your renderer would need to do is switch on the value of that new field, rather than doing the entire comparison AND rendering.
I have it! This works for me:
{
header: 'CSV',
dataIndex: 'csv',
flex:1,
renderer: function(grid, rowIndex, rowdata) {
var csv_data=rowdata.data.csv;
var crs_data=rowdata.data.crs;
if (csv_data != crs_data) {
rowIndex.tdCls = "red-class";
}
return csv_data;
}
},
{
header: 'CSV',
dataIndex: 'csv',
flex:1,
renderer: function(value, meta, record) {
var crs = record.get('crs');
if (value && crs)
{
if (value != crs) {
meta.tdCls = "red-class";
}
}
return value;
}
},
Rewritten for ExtJS 4, you can use the value as you set it in the dataIndex, and because that's a record the recommended extjs 4 way to get the value would be the get method.
Just a heads up there are a ton more properties on renderer, you can find the full list here:
http://docs.sencha.com/extjs/4.2.2/#!/api/Ext.grid.column.Column-cfg-renderer
I'm using ExtJS 3 and I need to enable/disable a specific text field when I select/de-select a checkbox, like in the example showed below:
{
fieldLabel: 'myCheckBox'
xtype: 'checkbox',
name: 'myCheckBox'
},{
fieldLabel: 'myTextField'
xtype: 'textfield',
name: 'myTextField',
disabled: true
}
As I understand it I have to use a listener in 'myCheckBox' like this:
listeners: {
change: function() {
}
}
But I don't know what parameters to pass to my function and how to target 'myTextField' and .enable() .disable() it. Can you please help me? Thank you very much.
Solution based on answers (thank you):
listeners: {
change: function(cb, checked) {
Ext.getCmp('myTextField').setDisabled(!checked);
}
}
and added the id tag to the textfield component like this:
id: 'myTextField'
If you are not sure what to pass as a parameter than Ext.getCmp() gives you the component. It takes id of the component as a parameter. In your case you have to assign id to textfield and can get it on change event as Ext.getCmp('myTextField'). Where myTextField is an id of textfield. Name and Id of a component can be same.
listeners: {
change: function() {
Ext.getCmp('myTextField').disable();
//or
Ext.getCmp('myTextField').enable();
}
}
There are a few ways to reference myTextField. The easiest is probably to give the field a ref (note that this approach does not work in ExtJS 4, where you are better off with a component query):
{
fieldLabel: 'myTextField'
xtype: 'textfield',
name: 'myTextField',
ref: '../myTextField'
disabled: true
}
Setting the ref will cause the textfield component to be referenced in a property of its owner or one of its ancestors. So then your listener can simply be something like this (the parameters passed to this function are listed in the doc):
change: function(cb, checked) {
me.myTextField.setDisabled(!checked);
}
You might need to tweak the ref path depending on your component hierarchy.
Example:
Using setDisabled API:
theStudentForm.findField('stud_name').setDisabled(true);
Using setOpacity API:
theStudentForm.findField('stud_name').labelEl.setOpacity(1);
Using readOnly API:
theStudentForm.findField('stud_name').setReadOnly(true);
I'm trying to make something that looks like: http://dev.sencha.com/deploy/ext-3.4.0/examples/grid/edit-grid.html
But I want to change Light column:
I want it to contain ids instead of actual values.
I can force combobox to separate values from presentation but not the actual column value (in fact I don't know where to store id-value mapping for column (not just for the editor)):
new Ext.grid.EditorGridPanel({
...
store: new Ext.data.Store ({
...
fields: [
'MagicId',
...
]
})
columns: [
{
header: 'Magic',
dataIndex: 'MagicId',
editor: new Ext.form.ComboBox({
store: new Ext.data.Store({
...
fields: ['id', 'title']}),
valueField: 'id',
displayField: 'title',
editable: 'false'
})
},
...
]
When I select "Magic title" in combobox I get MagicId in my grid anyway. I understand why it's happening but can't make it work the way I need it to work...
I tried to replace all unnecessary code with ... to help you reading.
Thank you for your attention.
Keep the ID field in your grid/store, then use the "renderer" property to display something else. ID-text mapping could be stored in an array or an object:
{
header: 'Magic',
dataIndex: 'MagicId',
renderer: function(value) {
return magicIdValueArray[value];
}
...
}
EDIT:
Since you already have the ID-value mapping in the combo store, I would use that store to fetch the value (it needs to be declared outside the combobox).
renderer: function(value) {
var record = comboStore.findRecord('id', value);
return record.title;
}