Extjs - Populate combobox whit store not match - extjs

I need populate a combobox whit a store, all work fine except one thing. ¿Why the store populate only the displayField and not the valueField.
In this line
form.loadRecord(records[1]);
I set that record in the form, is fine but when i try submit the form i hope the value "2" and not the value "Media".
The code and the example on Jsfiddle for better explanation.
http://jsfiddle.net/jjgrn/5/
var store = Ext.create('Ext.data.Store', {
fields: ['id', 'status'],
data: [
{ id: '1', status: 'Baja' },
{ id: '2', status: 'Media' },
{ id: '3', status: 'Alta' },
{ id: '4', status: 'Urgente' }
]
});
var formPanel = Ext.create('Ext.form.Panel', {
title: 'Edit Country',
url: 'http://aaa.com/',
items: [
{
xtype: 'combobox',
fieldLabel: 'Nombre',
name: 'status',
anchor: '50%',
displayField: 'status',
valueField: 'id',
store: store
}
],
buttons: [
{
text: 'Guardar',
handler: function () {
var form = formPanel.getForm();
var value = form.getValues();
alert(value.status);
}
}
],
renderTo: Ext.getBody()
});
store.load({
scope: this,
callback: function(records, operation, success) {
var form = formPanel.getForm();
form.loadRecord(records[1]);
}
});
Thanks.

It's because form.loadRecord() doesn't do exactly what you're expecting it to do.
What you want it to do is to tell combobox to use that particual record (records[1]).
What it actually does is to tell combobox: "now set your value to Media", which combobox politely does though it's too "stupid" to associate it with particular record.
Here's the fixed version, not sure if such solution fits your needs:
http://jsfiddle.net/jjgrn/6/
var store = Ext.create('Ext.data.Store', {
fields: ['id', 'status'],
data: [
{ id: '1', status: 'Baja' },
{ id: '2', status: 'Media' },
{ id: '3', status: 'Alta' },
{ id: '4', status: 'Urgente' }
]
});
var formPanel = Ext.create('Ext.form.Panel', {
title: 'Edit Country',
url: 'http://aaa.com/',
items: [
{
xtype: 'combobox',
fieldLabel: 'Nombre',
name: 'status',
anchor: '50%',
displayField: 'status',
valueField: 'id',
store: store
}
],
buttons: [
{
text: 'Guardar',
handler: function () {
var form = formPanel.getForm();
var value = form.getValues();
alert(value.status);
}
}
],
renderTo: Ext.getBody()
});
store.load({
scope: this,
callback: function(records, operation, success) {
// the operation object
// contains all of the details of the load operation
//var form = formPanel.getForm();
//form.loadRecord(records[1]);
formPanel.items.first().select(records[1]);
}
});

When you call form.getValues(), you only get the value, if you want the associated record for a value, you have to search the store. http://jsfiddle.net/jjgrn/7/
var rec = store.getById(value.status);
alert(rec.get('status'));
Key is understanding that getValues() just calls getValue() for each field in the form. getValue doesn't return a record, just the field from the record that you told it to use valueField: 'id',.

Related

Add record to the store and display on the grid

I have AddRecord method, that should add the record to the store and display on the grid that record.
I've put the form inside the window, and that is fine.
I was looking at the documentation but I got lost a bit.
There is a fiddle created.
Here is the fiddle: https://fiddle.sencha.com/#view/editor&fiddle/2tuf
AddRecord: function (grid, rowId, record) {
Ext.create('Ext.window.Window', {
title: "Add Person",
height: 200,
width: 400,
closeAction: 'hide',
closable: true,
items: [{
xtype:'form',
defaultType: 'textfield',
layout: 'anchor',
items: [{
fieldLabel: 'First Name',
name: 'First Name',
type: 'String',
allowBlank: false
}, {
fieldLabel: 'Last Name',
name: 'Last Name',
type: 'String',
allowBlank: false
}, ],
buttons: [{
text: 'Add',
formBind: true,
disabled: true,
handler: function () {
var record = Ext.getStore().getAt(rowId);
var store = grid.getStore('store.Personal')
var form = this.up('form').grid.getStore();
if (form.isValid()) {
form.add({
success: function (record) {
var store = grid.getStore('store.Personal')
store.add(record);
},
})
}
},
}, {
text: 'Close', handler: function () {
this.up('window').close();
}
}],
}]
}).show();
}
});
You were almost there, You made a little confusion about grid.getStore(), as it just
Returns the store associated with this Panel.
and how you are getting your form values, I think you were trying to do something like this:
buttons: [{
text: 'Add',
formBind: true,
disabled: true,
handler: function(button) {
let formValues = this.up('form').getForm().getValues(); //get the form Values
let form = this.up('form').getForm(); //get the form itself
var store = grid.getStore(); //get Store of your grid
if (form.isValid()) {
//add the formvalues to store
store.add(formValues);
}
},
}]
I also made a Fiddle

Form with textfield and grid: send all values to the server

In create and update forms, it is sometimes necessary to give the user the ability to dynamically add fields to values of the same type (more than one phone, more than one address, etc.).
I'm exploring several possibilities to do this.
One of them is to use a grid as a form field.
However, I have doubts about how best to implement this idea, especially on how to send all the form field values (textfield and grid) to the server (and then how to load them later in the form to edit).
Fiddles with some ideas:
One with cellediting plugin https://fiddle.sencha.com/#view/editor&fiddle/2ftp
Another one with roweditin gplugin a https://fiddle.sencha.com/#view/editor&fiddle/2fto
Not sure about the "best to implement", but I have seen so many requirements for multivalue input, that for reusability I have in my toolbox a gridfield similar to the following one:
Ext.define('Ext.ux.GridField', {
extend: 'Ext.form.FieldContainer',
alias: 'widget.gridfield',
initComponent: function () {
var me = this;
if(!me.columns) me.columns = {
dataIndex: 'field1'
};
if(!me.mapFn) me.mapFn = function(value) {
if(Ext.isObject(value)) return value;
return {
field1: value
};
};
if(!me.unmapFn) me.unmapFn = function(record) {
return record.get('field1');
};
me.grid = Ext.widget(Ext.apply({
xtype: 'grid',
viewConfig: {
markDirty: false
},
store: me.store || Ext.create('Ext.data.Store', {
fields: me.columns.map(function(column) {
return {
name: column.dataIndex,
type: column.dataType || 'auto',
defaultValue: column.defaultValue
};
}),
listeners: {
update: me.updateValue,
datachanged: me.updateValue,
scope: me
}
}),
columns: [{
xtype: 'actioncolumn',
getClass: function () {
return 'x-fa fa-times'
},
handler: function(grid, rowIndex, colIndex, item, e, record) {
grid.getStore().remove(record);
},
width: 35
}].concat(me.columns),
bbar: [{
xtype: 'button',
iconCls: 'x-fa fa-pencil',
text: 'Add',
handler: function(btn) {
var grid = btn.up('grid'),
store = grid.getStore(),
record = store.add(Ext.clone(me.emptyRecord) || {})[0];
grid.getPlugin('editor').startEditByPosition({
row: store.indexOf(record),
column: 1
});
}
}],
plugins: [
Ext.create('Ext.grid.plugin.CellEditing', {
pluginId: 'editor',
clicksToEdit: 1
})
]
}, me.gridConfig)); // "gridConfig" config can override everything on each instance.
me.hiddenField = Ext.widget({
xtype: 'hiddenfield',
name: me.name,
value: '',
allowNull: false,
rawToValue: function (raw) {
return raw;
},
valueToRaw: function (value) {
return value;
},
getRawValue: function () {
return Ext.valueFrom(this.rawValue, '')
},
isEqual: function (a, b) {
return Ext.encode(a) == Ext.encode(b)
},
listeners: {
change: function(field, nV, oV) {
if(!Ext.isArray(nV)) nV = [nV];
var store = me.grid.getStore();
store.removeAll();
store.add(nV.map(me.mapFn));
}
}
});
Ext.apply(me, {
layout: 'fit',
items: [{
xtype:'container',
border: 1,
style: {
borderColor: '#d0d0d0',
borderStyle: 'solid'
},
items: [me.grid]
}, me.hiddenField]
});
me.callParent(arguments);
},
updateValue: function() {
var me = this,
grid = me.grid,
hiddenField = me.hiddenField,
nV = grid.getStore().getRange().map(me.unmapFn, me),
oV = me.hiddenField.getValue();
if(!oV || Ext.isArray(oV) && Ext.encode(nV) != Ext.encode(oV)) {
hiddenField.suspendCheckChange++;
hiddenField.setValue(nV);
hiddenField.suspendCheckChange--;
me.fireEvent('change', me, nV, oV);
}
}
});
which can then be used like this:
},{
xtype: 'gridfield',
fieldLabel: 'Contacts',
name: 'contacts',
columns: [{
text: 'Type',
dataIndex: 'type',
editor:{
xtype: 'combobox',
name: 'type',
valueField: 'name',
displayField: 'name',
store: combostore,
queryMode: 'local'
},
flex: 0.7
},{
text: 'Description',
dataIndex: 'description',
editor:{
xtype: 'textfield',
name: 'description'
},
flex: 1
}],
mapFn: function(value) {
return value;
},
unmapFn: function(record) {
return record.getData();
}
}, {
I have made a fiddle for you based on your fiddle, including working load and save operations on the form, but in ExtJS 6.x. And I have checked that it works with ExtJS 5 as well, although you have to add working icons.

Record is undefined Extjs4 to get the data out of the form

I have window with button enter and few fields i need to get the data out of the form and there is method on button :
enter: function (button) {
var win = button.up('window'),
form = win.down('form'),
record = form.getRecord(),
values = form.getValues();
record.set(values);
win.close();
this.getUsersStore().sync();
Here record is undefined. What i do wrong?
////////////////////////////////////////////////////////////////////
Here the form:
Ext.define('ExtMVC.view.portlet.Login', {
extend: 'Ext.window.Window',
alias: 'widget.login',
layout: 'fit',
title: 'LogIn',
width: 300,
height: 150,
autoShow: true,
store: 'LoginModels',
initComponent: function () {
this.items = [
{
xtype: 'form',
items: [
{
xtype: 'textfield',
name: 'Name',
fieldLabel: 'Name',
style: { 'margin': '10px' },
},
{
xtype: 'textfield',
name: 'Password',
fieldLabel: 'Password',
style: { 'margin': '10px' },
}
]
}
];
this.buttons = [
{
text: 'Enter',
action: 'enter',
//handler: this.enter
},
{
text: 'Cancel',
scope: this,
handler: this.close
},
{
text: 'Sing in',
scope: this,
handler: this.close
}
];
this.callParent(arguments);
}
});
try to replace with this code
values=form.getForm().getValues();
Please go through the ext doc as it clearly says:
getRecord( ) : Ext.data.Model :
Returns the currently loaded Ext.data.Model instance if one was loaded via loadRecord.
And in case of your example I dont see any code that loads your form panel using loadRecord().
enter: function (button) {
var win = button.up('window'),
form = win.down('form'),
//record = form.getRecord(), /*not required here*/
record = this.getUsersStore().findRecord('id', 1) /*if you know id or some thing which field is know*/
values = form.getValues();
record.set(values);
win.close();
this.getUsersStore().sync();
You have to load form using form.loadRecord() before fetching it through form.getRecord(), otherwise form.getRecord() returns undefined.

EXTJS - 2 Grids with checkbox model--disable checkbox in one grid if corresponding checkbox in other grid is selected?

I have two grids with the same records, but different stores.
Basically, if record A is selected in grid A, i want to disable the checkbox for record A in grid B.
I know I can listen for "beforeselect" event on either grid,for example grid A, but then how would i "get" the records from grid B? Once I have the recs, I can check to see if its selected or not, then I can enable/disable checkbox for other grid by simply returning true/false.
thank you
Ok, I ended up doing a checkcolumn as it was easier to do in line code. You can throw this code in fiddle.sencha.com and it will work.
Panel 1 in the example is the one you can check and it will return the values of Panel1 and compare them against Panel2 and state if the check value on both. You could then do whatever you wanted.
If you did the selection model route you would put a change function in the controller and in the function just do something like:
var gridSelected = Ext.ComponentQuery.query('panel1')[0].getSelectionModel().getSelection();
Ext.each(gridSelected, function (value) {
//something
}
Below is the inline code:
Ext.onReady(function() {
var locationStore = Ext.create('Ext.data.Store', {
fields: ['id', 'location', 'check'],
proxy: {
type: 'memory'
},
data: [{
id: 1,
location: 'location 1',
check: false
}, {
id: 2,
location: 'location 2',
check: false
}, {
id: 3,
location: 'location 3',
check: false
}, {
id: 4,
location: 'location 4',
check: false
}, {
id: 5,
location: 'location 5',
check: false
}]
});
var locationStore2 = Ext.create('Ext.data.Store', {
fields: ['id', 'location', 'check'],
proxy: {
type: 'memory'
},
data: [{
id: 1,
location: 'location 1',
check: false
}, {
id: 2,
location: 'location 2',
check: false
}, {
id: 3,
location: 'location 3',
check: false
}, {
id: 4,
location: 'location 4',
check: false
}, {
id: 5,
location: 'location 5',
check: false
}]
});
Ext.create('Ext.grid.Panel', {
renderTo: Ext.getBody(),
xtype: 'panel1',
height: 200,
width: 350,
store: locationStore,
columns: [{
text: 'ID',
dataIndex: 'id'
}, {
text: 'Location',
dataIndex: 'location',
flex: 1,
},{
xtype: 'checkcolumn',
header: 'Check',
dataIndex: 'check',
width: 90,
listeners: {
checkchange: function (column, recordIndex, checked) {
var view = panel2.getView(),
record = view.getRecord(view.getNode(recordIndex));
var p1ID = record.get('id');
var p1Check = checked;
Ext.each(locationStore2.data.items, function (value)
{
var p2ID = value.data.id;
var p2Check = value.data.check;
if (p1ID == p2ID){
//here we output the results and you could also do something here.
console.log(p1ID, p1Check, p2ID, p2Check);
}
})
}
}
}]
});
var panel2 = Ext.create('Ext.grid.Panel', {
renderTo: Ext.getBody(),
xtype: 'panel2',
height: 200,
width: 350,
store: locationStore2,
columns: [{
text: 'ID',
dataIndex: 'id'
}, {
text: 'Location',
dataIndex: 'location',
flex: 1,
},{
xtype: 'checkcolumn',
header: 'Check',
dataIndex: 'check',
width: 90,
listeners: {
checkchange: function (column, recordIndex, checked) {
var view = panel2.getView(),
record = view.getRecord(view.getNode(recordIndex));
console.log(record.get('id'));
}
}
}]
});
});
Thanks for your answer Jesse. I had came up with this, it was actually quite simple. I listened for the "beforeselect" event on both grids in controller:
//beforeselect handler
gridAHandler: function (grid, rec) {
var gridBSelections = this.getGridB().getSelectionModel().getSelection();
for(var i = 0; i<gridBSelections.length; i++) {
if(rec.get("NAME") == gridBSelections[0].data.NAME) {
return false;
}
}
}
So if i go to make a selection on gridA, the for loop will check to see if its corresponding column in gridB has been selected. If its selected, it will be in the gridBSelections array, so gridA NAME will equal gridB NAME (NAME columns on both grids share the same values), so i return false;
of course, handler for gridB will be exactly the same but with opposite values.``
posted this as another solution for anyone having the same prob.
thx

Ext 4.1.1: Add new record to Store

I would like to add records after the initialization of a store.
I tried loadData(), loadRawData(), add() but nothing seams to work.
Here is my jsfiddle: http://jsfiddle.net/charlesbourasseau/zVvLc
Any ideas ?
You need to set queryMode: 'local' in the combo box. Minimal example:
Ext.onReady(function() {
var store = Ext.create('Ext.data.Store', {
alias: 'store.ModeStore',
autoLoad: false,
fields: [{
name: 'mode',
type: 'string'
}, {
name: 'id',
type: 'string'
}],
data: [{
mode: 'mode1',
id: 1
}]
});
var container = Ext.create('Ext.form.field.ComboBox', {
renderTo: Ext.getBody(),
displayField: 'mode',
valueField: 'mode',
store: store,
queryMode: 'local'
});
store.add({
mode: 'mode2',
id: 2
});
});
For a panel you can add or remove items by remove() and add()
var store = Ext.create('MyApp.store.Roles', {autoLoad: false});
store.load(function(records, action, success) {
if (success) {
store.remove(store.findRecord('id', 50, 0, false, true, true));//exact match
store.add({'id':110,'name':'Agent' });
}
});

Resources