Best way to use checkboxes inside a Extjs Pivot Grid - extjs

I have a pivot grid which display if the users have create,read,update,delete" permissions, the users are agrouped in this way departaments > estabilishments > sectors > users and i want the user to be able to edit this fields.
I already tried using with a renderer:
aggregate: [{
renderer: function(value, record, dataIndex, cell, column) {
var id = Ext.id();
Ext.defer(function() {
Ext.widget('checkbox', {
renderTo: id,
checked: value,
listeners: {
change: {
fn: function(event, target) {
//some function here
}
}
}
});
}, 100);
return Ext.String.format('<div id="{0}"></div>', id);
},
aggregator: 'aggCheckBoxR',
dataIndex: 'Incluir',
header: 'Incluir'
}]
and with a widget column:
aggregate: [{
aggregator: 'aggCheckBoxR',
column: {
xtype: 'widgetcolumn',
widget: {
xtype: 'checkbox',
listeners: {
change: function(cb) {
//some function here
}
}
}
},
dataIndex: 'Incluir',
header: 'Incluir'
}]
My Aggregator:
aggCheckBoxR: function(records, measure, matrix, rowGroupKey, colGroupKey) {
if (records.length > 1) {
let checkAllTrue = true;
for (var i = 0; i < records.length; i++) {
if (records[i].get('Incluir') === false || records[i].get('Incluir') === 0) {
checkAllTrue = false;
}
}
return checkAllTrue;
} else {
return records[0].get('Incluir');
}
}
The checkbox apears on the grid but my problem is the data "dont persist", whenever i expand or collapse a left axis on the pivot grid the value of the checkbox returns to its original value, how can i persist this data?
Already tried update the record manualy
change: function(cb) {
var nomeCmp = cb.getWidgetRecord().data._compactview_;
Ext.getStore('acesso.ColabStore').findRecord('Nome', nomeCmp).data.Incluir = true;
}
But still, it doestn't work.
EDIT: Had to change the column object event listener to:
{
xtype: 'widgetcolumn',
widget: {
xtype: 'checkbox',
listeners: {
afterrender: function(component, eOpts) {
console.log('after,render');
component.getEl().on('change', function(e, el) {
console.log('change func here');
})
}
}
}
}
With this, the change event is only fired when the users check a checkbox, and finally, I could use
norbeq's answer

You can update the record manually using:
record.set('Incluir',true);
and if you dont wan't to send changes to server:
record.commit();

Related

ExtJS 6 - Bind disabled property to new records in a store

I'm trying to enable/disable a button when the store getNewRecords() function return the length, but not work!
bind: {
disabled: "{!grid.getStore().getNewRecords().length}"
}
Fiddle: https://fiddle.sencha.com/fiddle/1sj5
Someone have idea to how resolve this?
You need to create a formula in your viewmodel:
viewModel: {
formulas: {
hasNewRecords: function (r) {
return this.getView().down("treepanel").getStore().getNewRecords().length > 0;
}
}
}
then you can use it for your bindings:
bind: {
disabled: "{hasNewRecords}"
}
(probably not the best way to get the data you want).
You can read about it here, here and here .
What you're wanting to do here is currently not possible in the framework. Instead, you should create a ViewModel data value and modify that where need be, like this:
var form = Ext.create("Ext.form.Panel", {
viewModel: {
data: {
newRecords: false
}
},
items: [{
xtype: "textfield",
labelField: "Add Child",
name: "col1",
value: "Teste 123"
}],
tbar: {
xtype: "button",
text: "Add new record",
handler: function () {
var data = this.up("form").getForm().getFieldValues();
var rec = grid.getStore().getAt(0);
data["treeCol"] = rec.childNodes.length + 1;
// setting value, so binding updates
this.lookupViewModel().set('newRecords', true);
rec.appendChild(data);
}
},
bbar: {
xtype: "button",
text: "button to disabled when new records",
bind: {
disabled: "{newRecords}"
}
},
renderTo: Ext.getBody()
});
Or by simply doing this.
In your controller:
me.getView().getViewModel().set('storeLen', store.getNewRecords().length);
In your ViewModel, simply do this:
formulas : {
hasNewRecords : {
get : function(get){
var length = get('storeLen') // --> gets the one you set at your controller
return length > 0 ? true : false;
}
}
}
In your View:
bind : {
disabled : '{hasNewRecords}'
}

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.

A formPanels textfield value should be a href link

this is my textfield in my formpanel:
{
xtype: 'textfield',
fieldLabel: 'Homepage',
name: 'homepage',
tabIndex: 4,
padding: '10'
}
I want the loaded value which is displayed to be a clickable link.
EDIT:
because webpages without "http://" at the beginning won't display in the new tab, i changed the solution a little bit like this:
listeners: {
render: function (field) {
this.getEl().on('click', function (e, t, eOpts) {
var url = e.target.value;
if (url != '') {
if (url.indexOf("http://") != -1) {
var win = window.open(url, '_blank');
} else {
var win = window.open('http://' + url, '_blank');
}
win.focus();
}
}
}
}
There is no way you can achieve what you desire.For 'link' you have to
use another component may be a label with a link.But with some trick you can make the value in a textfield appear as a link.For that you can do something like this:
{
xtype: 'textfield',
name: 'name',
id:'link',
fieldStyle: 'color: blue; text-decoration:underline; cursor:pointer',
listeners: {
render: function (field) {
this.getEl().on('click', function (e, t, eOpts) {
console.log(e);
//here you need to do some hack around to restrict changing href,only on click of input in the textfield.Could not achieve that,but tried to give some idea.
var url = e.target.value;
if(url != ''){
window.location="";
}
});
}
}
}
Hope this helps you :-)
To do this you can use the render function as follows:
{
xtype : 'displayfield',
id: 'yourId',
name:'yourName',
fieldLabel: 'This is the label',
renderer: function(data, field) {
return ''+data+''
}
}
It may not be the most elegant solution but it works :)

Go back to the selection in Data Grid after reloading the page ExtJS 4.1 [duplicate]

I have a problem. I use extjs grid. This grid will be refreshed every seconds.
I refresh with this function:
ND.refresh = function() {
ND.commList.load();
}
var refreshSeconds = refreshRate * 1000;
var t = setInterval('ND.refresh()', refreshSeconds);
But when someone selected a row to highlight it it reset this selection.
How can I remember the selected row and highlight it again after refresh?
This is my grid:
var grid = Ext.create('Ext.grid.Panel', {
autoscroll: true,
region: 'center',
store: ND.dashBoardDataStore,
stateful: true,
forceFit: true,
loadMask: false,
stateId: 'stateGrid',
viewConfig: {
stripeRows: true
},
columns: [{
text: 'Vehicle',
sortable: true,
flexible: 1,
width: 60,
dataIndex: 'vehicle'
}, {
text: 'CCU',
sortable: true,
flexible: 0,
width: 50,
renderer: status,
dataIndex: 'ccuStatus'
}]
});
Thanks guys
I wrote simple Ext.grid.Panel extension that automatically selects back rows that were selected before store reload. You can try it in this jsFiddle
Ext.define('PersistantSelectionGridPanel', {
extend: 'Ext.grid.Panel',
selectedRecords: [],
initComponent: function() {
this.callParent(arguments);
this.getStore().on('beforeload', this.rememberSelection, this);
this.getView().on('refresh', this.refreshSelection, this);
},
rememberSelection: function(selModel, selectedRecords) {
if (!this.rendered || Ext.isEmpty(this.el)) {
return;
}
this.selectedRecords = this.getSelectionModel().getSelection();
this.getView().saveScrollState();
},
refreshSelection: function() {
if (0 >= this.selectedRecords.length) {
return;
}
var newRecordsToSelect = [];
for (var i = 0; i < this.selectedRecords.length; i++) {
record = this.getStore().getById(this.selectedRecords[i].getId());
if (!Ext.isEmpty(record)) {
newRecordsToSelect.push(record);
}
}
this.getSelectionModel().select(newRecordsToSelect);
Ext.defer(this.setScrollTop, 30, this, [this.getView().scrollState.top]);
}
});
The straightforward solution is just save somewhere in js index of selected row. Then after reload you could easily select this row by index using grid's selection model.
Get selection model: http://docs.sencha.com/ext-js/4-0/#!/api/Ext.grid.Panel-method-getSelectionModel
var selectionModel = grid.getSelectionModel()
Get selected rows: http://docs.sencha.com/ext-js/4-0/#!/api/Ext.selection.Model-method-getSelection
var selection = selectionModel.getSelection()
Set selected row back: http://docs.sencha.com/ext-js/4-0/#!/api/Ext.selection.Model-method-select
selectionModel.select(selection)
Here is another way to select the previously selected record:
var selectionModel = grid.getSelectionModel()
// get the selected record
var selectedRecord = selectionModel.getSelection()[0]
// get the index of the selected record
var selectedIdx = grid.store.indexOfId(selectedRecord.data.id);
// select by index
grid.getSelectionModel().select(selectedIdx);
For some reason the grid.getSelectionModel().select(record) method wasn't working for me, but selecting by index seems to work.
Edit: found out why grid.getSelectionModel().select(record) method wasn't working. Apparently the store is reloaded, the record instances aren't the same (they have different automatically generated Ext IDs). You have to use selectAt() in this case.
for extjs 4.1.7 users
need a workarround about the statement in
refreshSelection() {
...
Ext.defer(this.setScrollTop, 30, this,
[this.getView().scrollState.top])
}
thus setScrollTop no longer exists
so a working soluction is add
me.getView().preserveScrollOnRefresh = true;
in initComponent
Ext.define('PersistantSelectionGridPanel', {
extend: 'Ext.grid.Panel',
selectedRecords: [],
initComponent: function() {
this.callParent(arguments);
this.getStore().on('beforeload', this.rememberSelection, this);
this.getView().on('refresh', this.refreshSelection, this);
//-------------------------------------------
me.getView().preserveScrollOnRefresh = true;
//-------------------------------------------
},
rememberSelection: function(selModel, selectedRecords) {
if (!this.rendered || Ext.isEmpty(this.el)) {
return;
}
this.selectedRecords = this.getSelectionModel().getSelection();
this.getView().saveScrollState();
},
refreshSelection: function() {
if (0 >= this.selectedRecords.length) {
return;
}
var newRecordsToSelect = [];
for (var i = 0; i < this.selectedRecords.length; i++) {
record = this.getStore().getById(this.selectedRecords[i].getId());
if (!Ext.isEmpty(record)) {
newRecordsToSelect.push(record);
}
}
this.getSelectionModel().select(newRecordsToSelect);
}
});
i have make modification on this code.
If you make selection, and aplys a filter on the store and reload it, the selection model have a first empty array in this selected collection ( at index 0 ).
This modification is in the last line of the "refreshSelection" function.
if (newRecordsToSelect.length >= 1){
this.getSelectionModel().select(newRecordsToSelect);
Ext.defer(this.setScrollTop, 30, this, [this.getView().scrollState.top]);
}

remember after refresh selected row in extjs grid

I have a problem. I use extjs grid. This grid will be refreshed every seconds.
I refresh with this function:
ND.refresh = function() {
ND.commList.load();
}
var refreshSeconds = refreshRate * 1000;
var t = setInterval('ND.refresh()', refreshSeconds);
But when someone selected a row to highlight it it reset this selection.
How can I remember the selected row and highlight it again after refresh?
This is my grid:
var grid = Ext.create('Ext.grid.Panel', {
autoscroll: true,
region: 'center',
store: ND.dashBoardDataStore,
stateful: true,
forceFit: true,
loadMask: false,
stateId: 'stateGrid',
viewConfig: {
stripeRows: true
},
columns: [{
text: 'Vehicle',
sortable: true,
flexible: 1,
width: 60,
dataIndex: 'vehicle'
}, {
text: 'CCU',
sortable: true,
flexible: 0,
width: 50,
renderer: status,
dataIndex: 'ccuStatus'
}]
});
Thanks guys
I wrote simple Ext.grid.Panel extension that automatically selects back rows that were selected before store reload. You can try it in this jsFiddle
Ext.define('PersistantSelectionGridPanel', {
extend: 'Ext.grid.Panel',
selectedRecords: [],
initComponent: function() {
this.callParent(arguments);
this.getStore().on('beforeload', this.rememberSelection, this);
this.getView().on('refresh', this.refreshSelection, this);
},
rememberSelection: function(selModel, selectedRecords) {
if (!this.rendered || Ext.isEmpty(this.el)) {
return;
}
this.selectedRecords = this.getSelectionModel().getSelection();
this.getView().saveScrollState();
},
refreshSelection: function() {
if (0 >= this.selectedRecords.length) {
return;
}
var newRecordsToSelect = [];
for (var i = 0; i < this.selectedRecords.length; i++) {
record = this.getStore().getById(this.selectedRecords[i].getId());
if (!Ext.isEmpty(record)) {
newRecordsToSelect.push(record);
}
}
this.getSelectionModel().select(newRecordsToSelect);
Ext.defer(this.setScrollTop, 30, this, [this.getView().scrollState.top]);
}
});
The straightforward solution is just save somewhere in js index of selected row. Then after reload you could easily select this row by index using grid's selection model.
Get selection model: http://docs.sencha.com/ext-js/4-0/#!/api/Ext.grid.Panel-method-getSelectionModel
var selectionModel = grid.getSelectionModel()
Get selected rows: http://docs.sencha.com/ext-js/4-0/#!/api/Ext.selection.Model-method-getSelection
var selection = selectionModel.getSelection()
Set selected row back: http://docs.sencha.com/ext-js/4-0/#!/api/Ext.selection.Model-method-select
selectionModel.select(selection)
Here is another way to select the previously selected record:
var selectionModel = grid.getSelectionModel()
// get the selected record
var selectedRecord = selectionModel.getSelection()[0]
// get the index of the selected record
var selectedIdx = grid.store.indexOfId(selectedRecord.data.id);
// select by index
grid.getSelectionModel().select(selectedIdx);
For some reason the grid.getSelectionModel().select(record) method wasn't working for me, but selecting by index seems to work.
Edit: found out why grid.getSelectionModel().select(record) method wasn't working. Apparently the store is reloaded, the record instances aren't the same (they have different automatically generated Ext IDs). You have to use selectAt() in this case.
for extjs 4.1.7 users
need a workarround about the statement in
refreshSelection() {
...
Ext.defer(this.setScrollTop, 30, this,
[this.getView().scrollState.top])
}
thus setScrollTop no longer exists
so a working soluction is add
me.getView().preserveScrollOnRefresh = true;
in initComponent
Ext.define('PersistantSelectionGridPanel', {
extend: 'Ext.grid.Panel',
selectedRecords: [],
initComponent: function() {
this.callParent(arguments);
this.getStore().on('beforeload', this.rememberSelection, this);
this.getView().on('refresh', this.refreshSelection, this);
//-------------------------------------------
me.getView().preserveScrollOnRefresh = true;
//-------------------------------------------
},
rememberSelection: function(selModel, selectedRecords) {
if (!this.rendered || Ext.isEmpty(this.el)) {
return;
}
this.selectedRecords = this.getSelectionModel().getSelection();
this.getView().saveScrollState();
},
refreshSelection: function() {
if (0 >= this.selectedRecords.length) {
return;
}
var newRecordsToSelect = [];
for (var i = 0; i < this.selectedRecords.length; i++) {
record = this.getStore().getById(this.selectedRecords[i].getId());
if (!Ext.isEmpty(record)) {
newRecordsToSelect.push(record);
}
}
this.getSelectionModel().select(newRecordsToSelect);
}
});
i have make modification on this code.
If you make selection, and aplys a filter on the store and reload it, the selection model have a first empty array in this selected collection ( at index 0 ).
This modification is in the last line of the "refreshSelection" function.
if (newRecordsToSelect.length >= 1){
this.getSelectionModel().select(newRecordsToSelect);
Ext.defer(this.setScrollTop, 30, this, [this.getView().scrollState.top]);
}

Resources