hide combo box value when already selected extjs - extjs

I have 2 combo box inside grid. The second combo box value will be change base on first combo box.
For example the combo has 3 item : America, Europe, Asia. If in the first combo box Europe is selected, then in the second combo box, Europe is not appear again.
I don't know which version of extjs I used, but here's the code :
MY COMBO STORE
var cb_group = Ext.create('Ext.data.Store', {
model: 'cb_group',
autoLoad: false,
proxy: {
type: 'ajax',
url: 'srv/master/group/combo',
reader: {
type: 'json',
root: 'rows'
}
}
});
MY COMBO INSIDE GRID
var set_approval_dtl = Ext.create('Ext.Window', {
title: title_approval2, width: 850, height: 395, rowdblclick: true, forceFit: true,
closeAction: "hide", store: ms_set_approval_dtl_store,
defaults: {
sortable: true, resizable: false
},
items: [
{xtype: "form", items: [
{layout: 'column', columnWidth: .5, itemId: 'set_approve', defaults: {border: false},
items: [{xtype: "panel", itemId: "set_approve_panel", height: 330, defaultType: 'textfield', margin: '0 10px 0 10px',
defaults: {labelWidth: 120, width: 850, maxLength: 200},
items: [
{xtype: "grid", itemId: "grid_items", width: 782, height: 280, margin: '0 10px 10px 10px', autoScroll: true,
plugins: Ext.create('Ext.grid.plugin.CellEditing', {clicksToEdit: 1, pluginId: 'rowEditing'}),
store: ms_set_approval_dtl_store, stripeRows: true, defaultType: "gridcolumn",
viewConfig: {forceFit: true},
columns: [
{header: grid18j, width: 150, dataIndex: 'nm_act', align: 'center'},
{header: subtitle_approval3, width: 126, dataIndex: 'level1', align: 'center',
editor: {xtype: "combobox", name: "cdgr", itemId: "cdgr1", typeAhead: true, editable: false, triggerAction: "all", forceSelection: true,
emptyText: grid8k, store: cb_group, valueField: "id", displayField: "nm",
listeners: {
expand: function(field, options, val) {
if (Ext.typeOf(field.getPicker().loadMask) !== "boolean") {
field.getPicker().loadMask.hide();
}
},
select: function(value) {
var obj = this.lastSelection[0].data;
return obj.nm;
this.lastSelection[0].hide;
cb_group.removeAt(0);
}
}},
renderer: function(val) {
var index = cb_group.findExact('id', val);
if (index !== -1) {
var rs = cb_group.getAt(index).data;
return rs.nm;
}
}
},
{header: subtitle_approval4, width: 126, dataIndex: 'level2', align: 'center', itemId: "level2",
editor: {xtype: "combobox", name: "cdgr", itemId: "cdgr2", typeAhead: true, editable: false, triggerAction: "all", forceSelection: true,
emptyText: grid8k, store: cb_group, valueField: "id", displayField: "nm",
listeners: {
expand: function(field, options) {
if (Ext.typeOf(field.getPicker().loadMask) !== "boolean") {
field.getPicker().loadMask.hide();
}
}
}
},
select: function(value) {
var obj = this.lastSelection[0].data;
return obj.nm;
},
renderer: function(val) {
var index = cb_group.findExact('id', val);
if (index !== -1) {
var rs = cb_group.getAt(index).data;
return rs.nm;
}
}
}]
}]}
]}]}
]});
I've tried this.lastSelection[0].hide; and cb_group.removeAt(0); in the first combo. But it didn't work at all. And I dont know why my select listener is not working.
please share some solution. Thanks

You can use XTemplates to manage this kind of behavior with one store and two comboboxes.
At first you have to create an XTemplate for your list of items in the combobox:
// displayfield = displayfield configured in your combobox
var template = Ext.create('Ext.XTemplate',
'<tpl for=".">',
' <tpl if="[Ext.getCmp(\'combobox1\').getValue()] != id && [Ext.getCmp(\'combobox2\').getValue()] != id">',
' <div class="x-boundlist-item">{label}</div>',
' <tpl else>',
' <tpl if="id == null || id == \'\'">',
' <div class="x-boundlist-item">{label}</div>',
' <tpl else>',
' <div class="x-boundlist-item" style="font-size:0px; height:0px;"></div>',
' </tpl>',
' </tpl>',
'</tpl>'
);
The XTemplate contains some statements to check if the specific value is already selected in one of the comboboxes. If not, then the entry will appear in the dropdown list, otherwise it will be hidden. To make it work, you have to set the template in your combobox and add some listeners to them:
// Combobox 1
{
xtype: 'combo',
id: 'combobox1',
store: 'your_store',
tpl: template,
displayField: 'label',
valueField: 'id',
listeners: {
beforeSelect: function (combo, record, index, eOpts)
{
// Check if the selected value is already selected in combobox2
var cbx2value = !!Ext.getCmp('combobox2').getValue() ? Ext.getCmp('combobox2').getValue() : '';
if (cbx2value != record.get('id') && cbx2value != record.get('id')) {
return true; // selected entry will be selected successfully
} else {
return false; // selected entry will not be selected
}
},
change: function ()
{
// Get the picker (list of items) of the other combobox and refresh it's template state
var cbx2picker = Ext.getCmp('combobox2').getPicker();
cbx2picker.refresh();
}
}
// Combobox 2
{
xtype: 'combo',
id: 'combobox2',
store: 'your_store',
tpl: template,
displayField: 'label',
valueField: 'id',
listeners: {
beforeSelect: function (combo, record, index, eOpts)
{
// Check if the selected value is already selected in combobox2
var cbx1value = !!Ext.getCmp('combobox1').getValue() ? Ext.getCmp('combobox1').getValue() : '';
if (cbx1value != record.get('id') && cbx1value != record.get('id')) {
return true; // selected entry will be selected successfully
} else {
return false; // selected entry will not be selected
}
},
change: function ()
{
// Get the picker (list of items) of the other combobox and refresh it's template state
var cbx1picker = Ext.getCmp('combobox1').getPicker();
cbx1picker.refresh();
}
}
It's not the ultimate solution, but for one of my projects it worked like a charm. I have simplified the example as good as possible to make the solution clearer.

You will need two stores, one for each combo box, both filled with the same data.
And then you will do:
combo1.on('select',function(combo, newVal) {
combo2.getStore().filterBy(function(rec){
return rec.get("value")!=newVal;
})
});

Related

Checkboxgroup getting duplicates value on second call

I am displaying checkboxgroup on a window with other fields too.
But the second time I call the function to display this window with the checkboxgroup the checkboxgroup gets duplicated.
i.e It only displays two times and not multiple times.
Eg : If actual checkbox values are "red" , "green" then the result on second ,third call will be "red" , "red" , "green" , "green".
Even the +Checklist button displays twice on second or more calls.
It displays proper values on first call though.
below is the code I am working on.
var checkboxconfigs = [];
function showassetForm(record,statusname,emptyval)
{
var arrSubTicket = getSubTickets(record.data.Id);
for(z=0;z<arrSubTicket.length;z++)
{
checkboxconfigs.push({ //pushing into array
id:arrSubTicket[z].Id,
boxLabel:arrSubTicket[z].Name,
name:'checklist',
inputValue:arrSubTicket[z].Id,
relatedTicket:arrSubTicket[z].TicketId
//any other checkbox properties, layout related or whatever
});
}
var myCheckboxGroup = Ext.create('Ext.form.CheckboxGroup', {
columns: 1,
vertical: true,
items: checkboxconfigs
});
myCheckboxGroup.on({
change: function(checkboxGroup, newValue) {
formattedValues = [];
newValue = newValue.checklist.length === 0 ? [newValue.checklist] : newValue.checklist;
checkboxGroup.items.each(function(checkbox){
var checkboxValue = checkbox.inputValue,
foramttedValue = {};
foramttedValue[checkboxValue] = newValue.indexOf(checkboxValue) !== -1 ? 'on' : 'off';
formattedValues.push(foramttedValue);
});
}
});
form = Ext.widget('form', {
layout: {
type: 'vbox',
align: 'stretch'
},
border: false,
bodyPadding: 10,
fieldDefaults: {
labelAlign: 'top',
labelWidth: 100,
labelStyle: 'font-weight:bold'
},
defaults: {
margins: '0 0 10 0'
},
items: [{
xtype: 'fieldcontainer',
labelStyle: 'font-weight:bold;padding:0',
layout: 'vbox',
defaultType: 'textfield',
fieldDefaults: {
labelAlign: 'left'
},
items: [
/*{
flex: 1,
name: 'Name',
fieldLabel: 'Ticket Description',
allowBlank: true
},*/
{
name: 'Hours',
fieldLabel: 'Hours',
allowBlank: true,
value: record.data.Hours
},
{
flex: 2,
xtype:'textarea',
name: 'Notes',
fieldLabel: 'Ticket Notes',
allowBlank: true
},
{
xtype: 'combo',
fieldLabel: 'Status',
hiddenName: 'Status',
allowBlank: false,
name:'Status',
store: new Ext.data.SimpleStore({
data: allstatus,
id: 0,
fields: ['value', 'text']
}),
// valueField: 'value',
valueField: 'value',
displayField: 'text',
triggerAction: 'all',
editable: false,
// value : record.data.Status
value : statusname
},
{
xtype: 'combo',
fieldLabel: 'Priority',
hiddenName: 'Priority',
allowBlank: false,
name:'Priority',
store: new Ext.data.SimpleStore({
data: priorities,
id: 0,
fields: ['value', 'text']
}),
// valueField: 'value',
valueField: 'value',
displayField: 'text',
triggerAction: 'all',
editable: false,
value : record.data.Priority
},
{
xtype: 'button',
id: 'newSubTicket',
cls:'x-btn-default-small',
text: '+ Checklist',
handler : function () {
createSubticket(record,statusname);
},
style : 'margin:0 0px'
},
myCheckboxGroup
]
}],
buttons: [{
text: 'Cancel',
handler: function() {
this.up('form').getForm().reset();
this.up('window').hide();
}
}, {
text: 'Save',
handler: function() {
if (this.up('form').getForm().isValid())
{
// In a real application, this would submit the form to the configured url
// this.up('form').getForm().submit();
form = this.up('form').getForm();
var recordsToAdd = [],recordsToAddNotes = [];
var record1 = {},recordNotes = {};
//this.up('window').hide();
//var summary = form.findField('Name').getSubmitValue();
var hrs = form.findField('Hours').getSubmitValue();
var status = form.findField('Status').getSubmitValue();
var priority = form.findField('Priority').getSubmitValue();
var notes = form.findField('Notes').getSubmitValue();
record1['ccfive_related_ticket_status']=status;
record1['dev_priority']=priority;
record1['io_uuid'] = record.data.Id;
//console.log("TicketName="+record.data.TicketName);
recordsToAdd.push(record1);
recordNotes['dev_note'] = notes;
recordNotes['dev_hours'] = hrs;
recordNotes['dev_related_punchlist_item'] = record.data.Id;
recordNotes['ccfive_related_ticket_status'] = status;
recordsToAddNotes.push(recordNotes);
}
}
}]
});
win = Ext.widget('window', {
title: record.data.TicketName,
closeAction: 'hide',
width: 400,
height: 450,
minHeight: 220,
layout: 'fit',
resizable: true,
modal: true,
items: form
});
win.show();
}
This is what I get on first call
But after clicking on cancel and calling the function it displays me.
Duplicate checkboxes and checklist button on second call
Move var checkboxconfigs = []; into showassetForm function
function showassetForm(record, statusname, emptyval) {
var checkboxconfigs = [];
var arrSubTicket = getSubTickets(record.data.Id);
The issue was just of passing id to some parameters on form.
Extjs sometimes behaves weird if Id is passed.
Removed id parameter and it worked fine!
Try and avoid duplicate ids (see comment "double check this"):
for(z=0;z<arrSubTicket.length;z++)
{
checkboxconfigs.push({
id:arrSubTicket[z].Id, // <==================== double check this!!
boxLabel:arrSubTicket[z].Name,
name:'checklist',
inputValue:arrSubTicket[z].Id, // <============ double check this!!
relatedTicket:arrSubTicket[z].TicketId
});

how set selected row in checkbox grid panel extjs depends textfield value

i have a grid panel and i want checked the row same as the value of text field.
anyone can help me.?
this is my code:
var check = new Ext.selection.CheckboxModel({
checkOnly : true,
listeners: {
change: function(checkbox, value) {
}
}
});
Ext.create('Ext.form.Panel', {
renderTo: "example-grid",
bodyStyle: 'padding: 5px 5px 0 5px;',
items: [
{
xtype: 'textfield',
fieldLabel: 'Group Fields ',
value:'a',
readOnly: true,
inputId: 'group'
}]
});
var grid1 = Ext.create('Ext.grid.Panel', {
title: 'Group Fields',
id:'gridPanel',
selModel: check,
store: Ext.data.StoreManager.lookup('tes'),
columns: [{
text: 'Field',
dataIndex: 'field',
flex: 1
}],
viewConfig: {
markDirty: false
},
height: 200,
width: 200
});
my fiddle example:
http://jsfiddle.net/y0uzha/f73kx37e/1/
Looks like you just need one-way binding so I would suggest to apply a selectionchange listener to the selectionModel to set the value of the groupField. See grid1#listeners#viewready. Note: I added an id to the form panel so that you can get a handle on it.
Generally speaking you should not use the id propery on child components, so they can be reusable. It would be better practice to use a viewport or a global parent container that has an id. Also, it would be best practice to use a controller to wire all this business logic together. Enjoy!
var check = new Ext.selection.CheckboxModel({
checkOnly: true
});
Ext.create('Ext.form.Panel', {
id: 'formPanel',
renderTo: "example-grid",
bodyStyle: 'padding: 5px 5px 0 5px;',
items: [{
itemId: 'groupField',
xtype: 'textfield',
fieldLabel: 'Group Fields ',
readOnly: true,
inputId: 'group'
}]
});
var grid1 = Ext.create('Ext.grid.Panel', {
title: 'Group Fields',
id: 'gridPanel',
selModel: check,
store: Ext.data.StoreManager.lookup('tes'),
columns: [{
text: 'Field',
dataIndex: 'field',
flex: 1
}],
viewConfig: {
markDirty: false
},
listeners: {
viewready: function() {
var selModel = this.getSelectionModel();
//Bind the groupField's value to the selected records
selModel.on('selectionchange', function(selModel, selections, eOpts) {
var groupField = Ext.getCmp('formPanel').queryById('groupField'),
groupValues = Ext.pluck(Ext.pluck(selections, 'data'), 'field');
groupField.setValue(Ext.Array.sort(groupValues).toString());
});
//Initially selects the first item in the grid
selModel.selectRange(0, 0);
}
},
height: 200,
width: 200
});

Ext table layout

I have a table with two rows and two columns - but I want to order each row differently.
The first row: (first column - width:30px, second column - width:270px)
The second row: (first column - width:130px, second column - width:170px).
I can't extract the two rows to different containers. I need to change the table.
My code is:
var replacePanel = new Ext.Container({
id:'replacePanel',
layout:'table',
border: false,
layoutConfig:{columns: 2},
style: { "padding-bottom": "5px", margin: "5px 0 0 20px" ,"white-space":"normal"},
items:[
{
xtype: "checkbox",
name: 'replace_cb', id: 'replace_cb',
width: 15, style: "margin-top:5px;",
listeners: {
check: function (checkbox, checked) {
var settingsForm = Ext.ComponentMgr.get('settingsForm');
settingsForm.changedFormula = true;
replacePanel.findById("replace_column").setDisabled(!checked);
}
}
},
{
xtype: "label", width: 390,
text: getDomElement("profileSetting.customMetrics.useNewMetric").value,
style:'padding-left:5px; padding-right:5px; margin-top:5px'
},
{
xtype: "container", width:160, style: "margin-top:4px", items: [
{
xtype: "combo", width: 150,
name:'replace_column',
id:'replace_column',
allowBlank:false, editable: false, typeAhead: true, disabled: true,
triggerAction: 'all', lazyRender:true, mode: 'local',
store: new Ext.data.JsonStore({ id: 'storeForReplaceColumn', fields: ['id', 'displayText'] }),
valueField: 'id',
displayField: 'displayText',
listeners: {
afterrender: function(combo) {
if (Ext.isIE) {
Ext.get(combo.el.dom.parentNode).setWidth(160);
}
},
select : function() {
var settingsForm = Ext.ComponentMgr.get('settingsForm');
settingsForm.changedFormula = true;
}
}
}]
},
{
xtype: "container",
html: getDomElement("profileSetting.customMetrics.whenReplacingMetrics").value
}
]
});
Table layout is not very good choice in this case. I would go for vbox layout for rows and hbox layout for columns.
Pseudo code:
vbox
item 1 (hbox)
left cell
right cell
item 2 (hbox)
left cell
right cell

Combo box in Extjs editor grid not displaying initally

I am trying to edit an information using editor grid. I have three fields, Interview By (combo), Date (date) and Performance (number), I get the date and the performance column, but the combo is not displaying the value initially. But when I click, then it shows the correct value. I am new to extjs and googled it for a solution, but could not find it. Kindly help me with a solution. Thanks in advance.
MY CODE:
initComponent: function() {
this.createTbar();
this.columns = [
{ xtype:'numbercolumn',
hidden:true,
dataIndex:'interview_id',
hideable:false
},
{ xtype: 'gridcolumn',
dataIndex: 'interview_by_employee_id',
header: 'Interview By',
sortable: true,
width: 290,
editor: {
xtype: 'combo',
store: employee_store,
displayField:'employee_first_name',
valueField: 'employee_id',
hiddenName: 'employee_first_name',
hiddenValue: 'employee_id',
mode: 'remote',
triggerAction: 'all',
forceSelection: true,
allowBlank: false ,
editable: false,
listClass : 'x-combo-list-small',
style: 'font:normal 11px tahoma, arial, helvetica, sans-serif'
},
renderer: function(val){
index = employee_store.findExact('employee_id',val);
if (index != -1){
rs = employee_store.getAt(index).data;
return rs.employee_first_name;
}
}
},
{ xtype: 'gridcolumn',
dataIndex: 'interview_date',
header: 'Date',
sortable: true,
readOnly: true,
width: 100,
editor: {
xtype: 'datefield'
}
},
{ xtype: 'numbercolumn',
header: 'Performance',
format:'0',
sortable: true,
width: 100,
align: 'right',
dataIndex: 'interview_performance',
editor: {
xtype: 'numberfield'
}
}
];
candidate_grid_interview.superclass.initComponent.call(this);
}
and the screen shots,
I faced the same problem and found my solution somewhere. Here is a reduced version of what I'm using. I think the key was the renderer property on the column. If your combo uses remote data, it might be loading its content after the grid is done loading - but I'm not sure it will cause the problem you're describing.
Try this concept:
var myStore = new Ext.data.JsonStore({
autoLoad: false,
...
fields: [
{ name: 'myID', type: 'int' },
{ name: 'myName', type: 'string' }
],
listeners: {
load: function () {
// Load my grid data.
},
scope: this
}
});
var myCombo = new Ext.form.ComboBox({
...
displayField: 'myName',
valueField: 'myID',
store: myStore
});
var grid = new Ext.grid.EditorGridPanel({
store: new Ext.data.ArrayStore({
...
fields: [
...
{ name: 'myID', type: 'int' },
...
]
}),
...
cm: new Ext.grid.ColumnModel({
columns: [
...
{
header: 'Header',
dataIndex: 'myID',
editor: myCombo,
renderer: function (value) {
var record = myCombo.findRecord(myCombo.valueField, value);
return record ? record.get(myCombo.displayField) : myCombo.valueNotFoundText;
}
}]
})
});
myStore.load();
Store loading is asynchronous, so it might be loading itself after rendering the grid. I recommend you render your grid within the store onload event. Also, datatypes can be painfull if you don't pay enough attention. Be sure that your grid store and combo store types match.

In ExtJs 3.3.1, how can I show a ComboBox drop down without click in EditorGrid?

I am using ExtJs 3.3.1.
Within an EditorGrid, my "editable" column has a ComboBox as its editor. How can I have the ComboBox always showing for each row? Meaning, the user would not have to click on a cell to know there is a ComboBox there. Currently, I have clicksToEdit set to 1, but I wish I could set this to 0 (I tried that).
See some of my code below to see my current configuration.
var combo = new Ext.form.ComboBox({
typeAhead: true,
triggerAction: 'all',
lazyRender: true,
mode: 'local',
store: new Ext.data.ArrayStore({
id: 0,
fields: [
'statusId',
'displayText'],
data: data
}),
valueField: 'statusId',
displayField: 'displayText'
});
var cm = new Ext.grid.ColumnModel({
columns: [{
id: 'orderId',
header: 'ID',
dataIndex: 'id',
width: 50
}, {
header: 'Status',
dataIndex: 'status',
width: 130,
editor: (data.length == 1) ? null : combo,
renderer: Ext.util.Format.comboRenderer(combo)
}, {
id: 'orderSummary',
header: 'Summary',
dataIndex: 'summary',
renderer: this.renderSummary
}]
});
var orderGrid = new Ext.grid.EditorGridPanel({
store: this.getOrderStore(),
cm: cm,
autoExpandColumn: 'orderSummary',
clicksToEdit: 1
});
Here is the solution I came up with.
In my column model, I made sure that the column I am making "editable" has an id. Each cell in that column will now have a CSS class associated with it named "x-grid-col-{id}". My column id is "status" so the class was "x-grid-col-status".
I created the CSS for class "x-grid-col-status" which sets the dropdown arrow image as the background, aligned right. It also sets the cursor to pointer, so the user knows they can click on the cell.
.x-grid3-col-status
{
background-image: url(Image/trigger-single.gif);
background-position: right;
background-repeat: no-repeat;
cursor: pointer;
}
Next, I set up a listener for my ComboBox that listens for the 'focus' event. On focus, I expand the drop down. It is important that I had to add lazyInit: false to my ComboBox config, or else an empty list will appear when you expand. lazyInit - true to not initialize the list for this combo until the field is focused (defaults to true)
The code:
Ext.util.Format.comboRenderer = function (combo) {
return function (value, metaData, record, rowIndex, colIndex, store) {
var record = combo.findRecord(combo.valueField, value);
return record ? record.get(combo.displayField) : combo.valueNotFoundText;
}
}
var combo = new Ext.form.ComboBox({
typeAhead: true,
triggerAction: 'all',
lazyInit: false,
lazyRender: true,
mode: 'local',
editable: false,
store: new Ext.data.ArrayStore({
id: 0,
fields: [
'statusId',
'displayText'
],
data: data
}),
valueField: 'statusId',
displayField: 'displayText',
listeners: {
'focus': {
fn: function (comboField) {
comboField.doQuery(comboField.allQuery, true);
comboField.expand();
}
, scope: this
}
, 'select': {
fn: function (comboField, record, index) {
comboField.fireEvent('blur');
}
, scope: this
}
}
});
var cm = new Ext.grid.ColumnModel({
defaults: {
sortable: true
},
columns: [
{
id: 'orderId',
header: 'ID',
dataIndex: 'id',
width: 50
}, {
header: 'Status',
id: 'status',
dataIndex: 'status',
width: comboColumnWidth,
editor: combo,
renderer: Ext.util.Format.comboRenderer(combo)
}, {
id: 'orderSummary',
header: 'Summary',
dataIndex: 'summary',
renderer: this.renderSummary
}
]
});
var orderGrid = new Ext.grid.EditorGridPanel({
store: this.getOrderStore(),
cm: cm,
autoExpandColumn: 'orderSummary',
title: title,
clicksToEdit: 1
});
I think you'll need to add a special css to the combo box that displays the drop down icon. This is natively not supported by Ext JS. Here's an example of how it can be done:
var companyColumn = {
header: 'Company Name',
dataIndex: 'company',
renderer: function(value, metaData, record, rowIndex, colIndex, store) {
// provide the logic depending on business rules
// name of your own choosing to manipulate the cell depending upon
// the data in the underlying Record object.
if (value == 'whatever') {
//metaData.css : String : A CSS class name to add to the TD element of the cell.
//metaData.attr : String : An html attribute definition string to apply to
// the data container element within the table
// cell (e.g. 'style="color:red;"').
metaData.css = 'name-of-css-class-you-will-define';
}
return value;
}
}
Or you could use the Ext.grid.TemplateColumn and specify the tpl config. This will automatically generate a renderer for the cells in the column and apply the tpl.

Resources