In an Ext.grid.panel I load a list of contents as rows with several columns. I would like the user to be able to select only one of these rows via a checkbox/radiogroup column, which has the ID of the respective entry as value.
I have already discovered the radiobuttons via the xtype widgtecolumn. But how can I set this column so that only one radiobutton in this column can be activated?
The current code for the radio column is the following:
{
xtype: 'widgetcolumn',
bind: {
text: 'Select topic'
},
dataIndex: 'defaultTopic',
widget: {
xtype: 'radio',
simpleValue: true
}
}
To ensure that the user can select only one radiobutton, you have to add the name property to your radio widget.
If you were using radiogroups like in this example, you'd have to add the name to each radiobutton. But for your use case, this configuration would be sufficient:
widget: {
xtype: 'radio',
simpleValue: true,
name: 'test'
}
See also this fiddle for an example.
You can use checkcolumn and change the records values that controls the check value using checkchange listener
Example:
{
xtype: 'checkcolumn',
text: 'Active',
dataIndex: 'active',
listeners: {
checkchange: 'onChangeDefaultTopic'
}
}
In your view controller:
onChangeDefaultTopic: function (column, rowIndex, checked, record) {
if (checked) {
store.getRange().forEach((rec) => {
if (record.get('id') !== rec.get('id')) {
rec.set('active', false)
}
});
}
}
Related
I have a widgetcolumn that contains a button:
xtype:'widgetcolumn',
dataIndex: 'canUpdateKey',
itemId:'updateKey',
width:120,
widget: {
xtype: 'button',
text: 'Update key',
hidden: '{!record.canUpdateKey}'
}
I only want to display the button where canUpdateKey is true on the record; but this does not work as indented. Relevant fiddle
From the widget config documentation:
The rendered component has a Ext.app.ViewModel injected which inherits
from any ViewModel that the grid is using, and contains two extra
properties: record and recordIndex
The widget configuration may contain a cfg-bind config which uses the
ViewModel's data.
So you should use bind instead, like this:
xtype:'widgetcolumn',
dataIndex: 'canUpdateKey',
itemId:'updateKey',
width:120,
widget: {
xtype: 'button',
text: 'Update key',
bind: {
hidden: '{!record.canUpdateKey}'
}
}
Fiddle: https://fiddle.sencha.com/#view/editor&fiddle/26ig
Inside your button widget, Try this:
listeners:{
render:function(btn){
if(!btn.getWidgetRecord().data.canUpdateKey)
btn.hide();
}
}
I'm new to ExtJS. So finding little difficult in understanding many things.
I've a sample combo box where I'm retrieving datas from the table
This is the combo box:
xtype: 'fieldset',
title: 'Dress Type',
items: [{
xtype: 'combobox',
name: 'dresses',
forceNewStore: true,
queryMode: 'local',
displayField: "description",
valueField: "description",
mapperId: 'getavailabletype',
emptyText: 'Select Type
forceSelection: true,
maskRe: /[A-Za-z0-9]/,
margin: '15px',
allowBlank: false,
triggers: {
clear: {
cls: 'x-form-clear-trigger',
handler: function() {
this.reset();
}
}
},
}]
Here is the way I'm trying to retain the first value of the table:
me.down("combobox[name=dresses]").setValue(me.down("combobox[name=dresses]").store.getAt('0').get('description'));
I'm getting:
Uncaught TypeError: Cannot read property 'get' of null #getAt('0')
Please help
I don't know from what listener and component you are trying to achieve this, but from my perspective, the best place to achieve this is in the "render" event listener of the combobox.
Like so:
listeners: {
'render': function(combo) {
combo.setValue(combo.getStore().first());
}
}
Here you have a working fiddle: https://fiddle.sencha.com/#view/editor&fiddle/1qqk
OR
If you have a reference to the combo store, let's say it's in the comboStore variable, you can set the first value like this:
{
xtype: 'combobox',
value: comboStore.first()
}
Another fiddle: https://fiddle.sencha.com/#view/editor&fiddle/1qql
Now, if you are not sure that the store will be loaded by the time you initialize your combo, you can set the following listener for the combobox:
listeners: {
render: function(combo) {
var store = combo.getStore(),
setFirstStoreValFn = function() {
combo.setValue(store.first());
};
if (store.getCount()) {
setFirstStoreValFn();
}
else {
store.on('load', setFirstStoreValFn, null, {single: true})
}
}
}
So basically, it creates a reusable function that sets the combo value to the first record in the store, and then it checks if the store has records (which means that is has been loaded) it will call the function, if not - it will set a single load listener on the store which will then call the set value function.
Again, the fiddle: https://fiddle.sencha.com/#view/editor&fiddle/1qqm
you need to navigate to cmp --> store --> first record ---> data
for that me.down("combobox[name=dresses]").store.getAt(0).get('description'))
I have the following application: https://fiddle.sencha.com/#view/editor&fiddle/1nmm. I'm using extjs 6.
After double click event on a row, I want to open a new tab. The new tab should contain a form with the information from the grid. My problem is that when I try to bind the displayfield value, the output is empty( nothing is shown).
xtype: 'displayfield',
fieldLabel: 'Id',
bind: {
value: '{record.data.ts_id}'
}
The above 'record' is declared as follow:
config: {
record: null,
rowIndex: null
},
bind: {
record: '{recordVM}',
rowIndex: '{rowIndexVM}'
}
How to properly bind to displayfield's value?
2 things:
1) Modify the way you're passing data to the viewmodel in the TabUIController:
viewModel: {
data: {
record: record,
rowIndex: rowIndex
}
}
There's no point trying to re-map those things.
2) Modify the bind statement in your view to value: '{record.ts_id}', the binding is smart enough to drill into the fields when it sees a record.
Try this:
TabUIGrid.js
bind: {
store :'{users}',
selection : '{myrecord}'
},
TabFormTest.js
{
xtype: 'displayfield',
fieldLabel: 'Name',
bind: '{myrecord.ts_name}'
}, {
xtype: 'displayfield',
fieldLabel: 'Email',
bind: '{myrecord.ts_email}'
}
I tested it on your fiddle and it works fine.
I have a requirement to display combobox and datefield in Grid columns. So used widgetcolumn and created grid with those fields.
But now on changing data in combobox or datefield, new values should be updated in grid store so that after going to next page and coming back, values should persist in previous pages.
Can someone let me know how I can achieve this?
Fiddle: https://fiddle.sencha.com/#fiddle/183r
Option1: Use both widget and cell editor.
Add CellEditing plugin and set editor to same component as widget.
{ xtype: 'widgetcolumn', text: 'Gender', dataIndex: 'gender', flex: 1,
widget: { xtype: 'combo', store: genderStore, displayField: 'name', valueField: 'value'},
editor: { xtype: 'combo', store: genderStore, displayField: 'name', valueField: 'value'}
},
Example: https://fiddle.sencha.com/#fiddle/1843
Option2: Manually update the record.
I feel this solution is better.
widget: {xtype: 'datefield',
listeners:{
select: function(datefield, value, eOpts){
var rowIndex = datefield.up('gridview').indexOf(datefield.el.up('table'));
var record = datefield.up('gridview').getStore().getAt(rowIndex);
record.set('dob', value);
}
}
}
Example: https://fiddle.sencha.com/#fiddle/1842
To get rowIndex in widgetColumn, I referenced "How to get rowIndex in extjs widget column" DrakeES's answer.
The best solution i could find.
The function "getWidgetRecord" is not findable with the search.
It is discribed within the widget config description.
Have a look at the following Links.
https://docs.sencha.com/extjs/5.1.3/api/Ext.grid.column.Widget.html#cfg-widget
https://docs.sencha.com/extjs/6.0.2/classic/Ext.grid.column.Widget.html#cfg-widget
A config object containing an xtype.
This is used to create the widgets or components which are rendered into the cells of this column.
This column's dataIndex is used to update the widget/component's defaultBindProperty.
The widget will be decorated with 2 methods: getWidgetRecord - Returns
the Ext.data.Model the widget is associated with. getWidgetColumn -
Returns the Ext.grid.column.Widget the widget was associated with.
widget:{
xtype:'combo',
editable: false,
store: Ext.create('Ext.data.Store',{
fields:['name','text'],
data:[
{"name":"integer", "text":"Integer"},
{"name":"float","text":"Float"}
]
}),
listeners:{
select: function(combo, value, eOpts){
var record = combo.getWidgetRecord();
record.set('type', value.get('name'));
}
},
valueField:'name',
displayField:'text',
allowBlank: false
}
or
widget: {
xtype: 'textfield',
allowBlank: false,
listeners:{
change: function(textfield, value, eOpts){
var record = textfield.getWidgetRecord();
record.set('field', value);
}
}
}
I'm using ExtJS 4.1.2, and I have an Ext.grid.Panel with a check-box selection model and a text-box in the header for filtering the items in the grid:
var nameStore = new Ext.data.Store({
...
proxy: { type: 'ajax' ... },
fields: [ { name: 'name', type: 'string' }, ... ],
});
var headerBar = new Ext.toolbar.Toolbar({
xtype: 'toolbar',
dock: 'top',
layout: 'fit',
items: [{
xtype: 'textfield',
...,
listeners: {
change: function(fld, newVal, oldVal, opts) {
var grid = ...;
if (newVal.length > 0)
grid.store.filterBy(function(record, id) { return record.get('name').indexOf(newVal) !== -1; });
else
grid.store.clearFilter()
}
}
}]
});
var nameGrid = new Ext.grid.Panel({
...
selType: 'checkboxmodel',
selModel: { mode: 'SIMPLE' },
store: nameStore,
columns: [ { dataIndex: 'name', flex: true }, ... ],
dockedItems: [ headerBar ],
bbar: [ { xtype: 'tbtext', text: '0 items selected' ... },
listeners: {
selectionchange: function(selModel, selected, opts) {
var txt = ...;
txt.setText(Ext.String.format("{0} items selected", selected.length));
}
}
});
As shown nameStore's filter is applied (or removed) based on the value in headerBar's textbox. Also, a text string in the bottom bar is updated as items are selected/deselected.
Each of these features is working smoothly on its own. But the interaction is giving me trouble: if an item is selected and then gets filtered out, it is deselected and then remains so when the filter is cleared.
How can I maintain the selections (or at least appear to do so to the user) of "hidden" items, either for use elsewhere in my application or to reselect when the filter is cleared? Thanks!
you need not to add the selected grid separately. This can be done in one grid only. Simple method is to have an array variable in page scope and capture the grid select event or itemclick event whatever you want.
e.g if you use select event it will give you your record.
select( this, record, index, eOpts )
you can get your record id and push it to the array variable that you declared.
Once you filtered out the grid. you can loop through the filtered records and call select method by getting selection model.
e.g
grid.getSelectionModel().select(record);
Hope this will help.