EXTJs Action Column icon - extjs

I want the icon to change from accept to delete when it is clicked on.
Set the iconflag = 1 because on page load I want the accept icon to be seen.
The code below doesn't satisfy the expectation
{
xtype: 'actioncolumn',
width: 30,
items: [{
flex: 1,
tooltip: 'Click to expand',
icon: iconflag == '1' ? "shared/icons/fam/accept.gif" : "shared/icons/fam/delete.gif",
getClass: this.getActionClass,
handler: function() {
if (iconflag == '1') {
iconflag = '0';
} else if (iconflag == '0') {
iconflag = '1';
}
alert(iconflag);
}
}]
},
Using EXTJs 4.2

In your handler function, iconflag is a local variable that loses its value outside the handler function. Where you use iconflag outside the handler function, it is evaluated only ONCE, before you click on the icon.
What you want to do is store your variable in a place that automatically forces the grid to update. Which is why you want to store the iconflag on the records in the store.
Add to your model another field:
{
name: 'iconflag',
type: 'bool',
defaultValue: false,
persist: false
}
Move the icons into CSS:
Ext.util.CSS.createStyleSheet([
'.iconflag-accept {',
' background-image: url(\'shared/icons/fam/accept.gif\')',
'}',
'.iconflag-delete {'
' background-image: url(\'shared/icons/fam/delete.gif\')',
'}'
].join(''));
Update the column to use the field:
dataIndex: 'iconflag',
getClass: function(iconflag) {
if(iconflag) return 'iconflag-delete';
else return 'iconflag-accept';
},
handler: function(view, colindex, rowindex, item, e, record) {
record.set('iconflag', !record.get('iconflag'));
}
Fiddle: https://fiddle.sencha.com/#view/editor&fiddle/205l

Related

Input field doesn't get cleared after choosing the value in the ExtJS tag field

I have the ExtJS tag field with anyMatch = true. Now if you type AB it will show the result and once you choose the selection it will clear the input you have entered i.e. AB Now when you have anyMatch= true that time if I type HI it will show you the result but when you choose the value the input field doesn't get cleared. I saw the ExtJS Tag field code it is handled explicitly in clearInput method. I wanted to know why this is implemented in this way ?
Below is the sample code
Ext.create('Ext.form.Panel', {
title: 'Tag Field Example',
width: 1000,
bodyPadding: 10,
items: [{
xtype: 'fieldcontainer',
labelWidth: 100,
layout: 'hbox',
items: [{
xtype: 'fieldcontainer',
defaults: {
flex: 1,
},
layout: 'hbox',
items: [{
xtype: 'tagfield',
minChars: 1,
anyMatch: true,
allowBlank: true,
margin: '5 5 5 5',
fieldLabel: 'Tag Field 1',
name: 'tagField1',
store: ['ABC D', 'EFG HI', 'C'],
queryMode: 'local',
filterPickList: true,
emptyText: 'Multi Select...'
}]
}]
}],
renderTo: Ext.getBody()
});
This seems to be a bug. If you take a look at the clearInput method from the tagfield class definition, and specifically at the section with the early return:
if (!Ext.String.startsWith(lastDisplayValue, inputValue, true)) {
return;
}
You can see that they discard clearing of the field if the last selected tag field value does not start with the typed input value ('abc d' starts with 'ab' so the field is cleared; 'efg hi' does not start with 'hi' - so the clearing is discarded).
This will clearly not work when you have the anyMatch config enabled.
The early return section from above, should be something like this:
if (!me.anyMatch) {
if (!Ext.String.startsWith(lastDisplayValue, inputValue, true)) {
return;
}
} else {
if (lastDisplayValue.toLowerCase().indexOf(inputValue.toLowerCase()) === -1) {
return;
}
}
We keep the initial check when anyMatch is not enabled, otherwise, we check if the typed input values is included in the last selected tag field value.
Here is a fiddle with the proposed override: https://fiddle.sencha.com/#view/editor&fiddle/32q0
I used arrays for multi string values (list item: Lincoln Abraham, input value: Abraham Lin).
That way method to checks if it matches properly.
In my implenmentation last part of the input string is used as wildcarded string. It also solves the problem where list item is reversed compare to input string, which was in my case.
clearInput: function() {
var me = this,
valueRecords = me.getValueRecords(),
inputValue = me.inputEl && me.inputEl.dom.value,
lastDisplayValue;
if (valueRecords.length && inputValue) {
lastDisplayValue = valueRecords[valueRecords.length - 1].get(me.displayField);
let inputValueArr = inputValue.split(' ');
let lastDisplayValueArr = lastDisplayValue.split(' ');
let matchCount = 0;
Ext.each(inputValueArr, function(iv, idx1, arr1) {
Ext.each(lastDisplayValueArr, function(ldv, idx1, arr2) {
if (!me.anyMatch) {
if (Ext.String.startsWith(ldv, iv, true)) {
matchCount++;
}
} else {
if (ldv.toLowerCase().indexOf(iv.toLowerCase()) !== -1) {
matchCount++;
}
}
});
});
if (matchCount < inputValueArr.length) {
return;
}
me.inputEl.dom.value = '';
if (me.queryMode === 'local') {
me.clearLocalFilter();
// we need to refresh the picker after removing
// the local filter to display the updated data
me.getPicker().refresh();
}
}
}

Best way to use checkboxes inside a Extjs Pivot Grid

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();

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.

Extjs state manager - save state from a dynamic form

I have a form that I add on click new fields. http://jsfiddle.net/Zb8DV/
the user can add his input and click on save.
I want onsave event to store the state in the cookie.
Next time when he enter to the form, I want to load the state, generate the fields in put the values last time he entered to the form.
So if you look at the form bellow:
you click on "add field" and a new field will be generated, after you add fields and put values, I want to save the state and load it next time...
Ext.state.Manager.setProvider(new Ext.state.CookieProvider());
Ext.create('Ext.form.Panel', {
renderTo: Ext.getBody(),
width: 500,
bodyPadding: 10,
title: 'Stateful',
stateful : true,
stateId : "MyFormState",
items: [{
xtype: 'button',
text: 'add field',
count: 0,
handler: function () {
this.count += 1;
var me = this;
this.up("form").add([{
"xtype": 'textfield',
name: 'field' + me.count,
fieldLabel: 'field ' + me.count
}]);
}
}, {
xtype: 'button',
margin : '10 10 10 100',
text: 'Save form state on click here',
handler : function(){alert("how do I load the panel with the state saved in cookie??")}
}],
});
In your button handler you can get values from form with getValues() method and then store values into cookies with Ext.state.Manager.set() method.
handler : function(btn){
var form = btn.up('form');
var values = form.getValues();
Ext.state.Manager.set('formFieldValues', values);
}
Restore form state from cookies you can in listener for form afterrender event. For getting form state from cookie you can use Ext.state.Manager.get() method.
listeners: {
afterrender: function(form) {
var values = Ext.state.Manager.get('formFieldValues');
if (values) {
console.log(values);
Ext.Object.each(values, function(key, value) {
form.count += 1;
form.add({
xtype: 'textfield',
name: 'field' + form.count,
fieldLabel: 'field ' + form.count,
value: value
});
});
}
}
}
Fiddle with complete example: https://fiddle.sencha.com/#fiddle/32e

Updating a value on an Ext.form.Panel

The following should be trivial, but I cannot get it to work:
I have the following Ext.form.Panel:
Ext.define('EvaluateIt.view.SiteEvaluationForm', {
extend: 'Ext.form.Panel',
alias : 'widget.siteEvaluationForm',
id: 'evaluationId',
requires: [
'Ext.form.Panel',
'Ext.form.FieldSet',
'Ext.field.Url',
'Ext.field.Select',
'Ext.field.Hidden'
],
config: {
// We give it a left and top property to make it floating by default
left: 0,
top: 0,
// Make it modal so you can click the mask to hide the overlay
modal: true,
hideOnMaskTap: true,
// Set the width and height of the panel
//width: 400,
//height: 330,
width: Ext.os.deviceType == 'Phone' ? screen.width : 300,
height: Ext.os.deviceType == 'Phone' ? screen.height : 500,
scrollable: true,
layout: {
type: 'vbox'
},
defaults: {
margin: '0 0 5 0',
labelWidth: '40%',
labelWrap: true
},
items: [
{
xtype: 'textfield',
name: 'address',
label: 'Address',
itemId: 'address'
},
{
xtype: 'hiddenfield',
itemId: 'imageUriId',
name: 'imageUri'
},
{
xtype: 'button',
itemId: 'siteImage',
text: 'Take Photo'
},
{
xtype: 'button',
itemId: 'save',
text: 'Save'
}
]
}
});
Which gets opened from an onItemDisclosure in a list view, and thus has a record bound to it.
When the 'siteImage' button is tapped, the user selects an image from the photo gallery and the uri is written to a temporary store for processing. This part works just fine.
What I need to do: When 'save' in the above form is tapped I need to take the uri from the temporary store and write it to the same store that all of the values from the above form get saved to.
To do this, I have the following method:
onSaveSiteEvaluation: function(button) {
console.log('Button Click for Save');
//var form = button.up('panel');
var form = Ext.getCmp('evaluationId');
//get the record
var record = form.getRecord();
//get the form values
//var values = form.getValues();
// return a clone for updating of values
var values = Ext.clone(form.getValues());
//if a new siteEvaluation
if(!record){
var newRecord = new EvaluateIt.model.SiteEvaluation(values);
Ext.getStore('SiteEvaluations').add(newRecord);
}
//existing siteEvaluation
else {
// get image uri from temp store
var images = Ext.create('EvaluateIt.store.ImageQueue');
images.queryBy(function(record,id){
images = Ext.getStore(images);
if (images.getCount() > 0) {
var uri = record.get('src');
// image = Ext.getCmp('imageUri');
//image = form.setValue(uri);
//form.getCmp('imageId').setValue(uri);
console.log('URI: ' + uri);
// THIS DOES NOT WORK!!
form.setValues({
imageUri: uri
})
//record.set('imageUri',uri)
console.log('imageUri: '+ record.get('imageUri'));
}
});
// do stuff
record.set(values);
}
form.hide();
//save the data to the Web local Storage
Ext.getStore('SiteEvaluations').sync();
},
Everything in this method works EXCEPT where I write the value of the uri to the form
form.setValues({
imageUri: uri
})
I've tried making 'uriImage' as an xType of hiddenfield and textfield, I've tried cloning the values from the form, etc. all with absolutely no luck in updating the actual attribute imageUri in the store (NOTE: All other form values are updated just fine). What am I missing? Thanks!
UPDATE
This works:
images.queryBy(function(iRecord,id){
images = Ext.getStore(images);
if (images.getCount() > 0) {
var uri = iRecord.get('src');
// update store with URI
form.setValues({
imageUri: uri
})
values = form.getValues();
record = form.getRecord();
}
});
// do stuff
record.set(values);
All's well that ends well!
Because Ext.form.Panel doesn't have setValue method. You first need to get basic form out of it:
form.getForm().setValue();
UPDATE: My bad, I was looking at the ExtJs docs and not Sencha Touch. your form does have setValue method.
After you call setValues(), can you go getRecord() again? Also looks like your record internal variable is defined twice. That should not be an issue, but...

Resources