I have a combo box with the multiSelect property and I want to know how can I know how many items were selected. I tried with:
combobox.store.getCount();
but it tells me the total of items in my combo box instead of the total of items selected by the user. Basically I want to make a condition that will trigger when the user selects more than one option in the combobox
You can use combo.getPicker() method and picker have method to get selected records
In this FIDDLE, I have created a demo using combobox with multi-select. I hope this will help you to achieve your requirement.
CODE SNIPPET
Ext.application({
name: 'Fiddle',
launch: function () {
// The data store containing the list of states
Ext.create('Ext.data.Store', {
fields: ['abbr', 'name'],
storeId: 'states',
data: [{
"abbr": "AL",
"name": "Alabama"
}, {
"abbr": "AK",
"name": "Alaska"
}, {
"abbr": "AZ",
"name": "Arizona"
}]
});
// Create the combo box, attached to the states data store
Ext.create('Ext.panel.Panel', {
title: 'Combo Example',
renderTo: Ext.getBody(),
items: [{
xtype: 'combo',
margin: 10,
fieldLabel: 'Choose State',
store: 'states',
queryMode: 'local',
displayField: 'name',
valueField: 'abbr',
multiSelect: true,
}],
bbar: ['->', {
text: 'Get Selected',
handler: function () {
var selectionModel = this.up('panel').down('combo').getPicker().getSelectionModel();
record = selectionModel.getSelection();
console.log(record);
Ext.Msg.alert('Info', 'Number of Selected record is ' + selectionModel.getCount());
//Ext.Msg.alert('Info', 'Selected record is <br> '+ record.map(r=>{return r.get('name')}).join('<br>'));
}
}]
});
}
});
Here is a possible solution. Go to multiselect-demo.html, open your browser console (F12 on Google Chrome and Firefox) and type :
f = Ext.getCmp("multiselect-field");
f.on("change", function () {
console.log(this.getValue().length)
});
Then see what's happening when you change the selected values in the "MultiSelect Test". For more informations, see : http://docs.sencha.com/extjs/4.2.5/#!/api/Ext.ux.form.MultiSelect-method-getValue.
Related
I have one widget column header by which I am selecting the value and filtering the grid store. I want exact the same on grid header as well. There for I am giving one combo with same values.
Here is my code for column header
header: {
items: [{
xtype: 'combo',
displayField: "displayName",
fieldLabel: 'Some Label',
valueField: 'title',
displayField: 'title',
hidden : true,
queryMode: 'local',
value : 1,
autoSelect : true,
//dataindex:"MUTST",
store: {
fields: ["id", "displayName"],
data: [
{ "id": "1", "title": "Test1" },
{ "id": "2", "title": "Test2" },
{ "id": "3", "title": "Test3" }
]
},
listeners : {
select : function(combo , record , eOpts){
debugger;
var sg = this.up("MyGrid");
var col = sg.getColumns()[0]; // Getting Header column
var flit =sg.getColumns()[0].filter // Here I am getting object instead of constructor
//this.focus = sg.onComboFilterFocus(combo);
}
},
}]
},
I am creating widget type in column
MyColumn: function(headersXmlDoc) {
var me = this,
gridConfig = {};
gridConfig.columns = [];
Ext.each(headersXmlDoc.getElementsByTagName("HEADER"), function(header) {
var column = {
text: header.getAttribute("L"),
dataIndex: header.getAttribute("DATAINDEX"),
sortable: (header.getAttribute("ISSORTABLE").toLowerCase()=="true"),
widgetType: header.getAttribute("WIDGET"),
filterType: Ext.isEmpty(header.getAttribute("FILTER"))? undefined: header.getAttribute("FILTER"),
};
switch (header.getAttribute("WIDGET")) {
case 'textbox':
if(column.filterType){
if(column.filterType == 'TagData'){
column.filter = {
xtype: 'tagfield',
growMax : 10,
valueField: 'title',
displayField: 'title',
parentGrid : me,
dataIndex:header.getAttribute("DATAINDEX"),
queryMode: 'local',
multiSelect: true,
isFilterDataLoaded: false,
disabled: true,
listeners:{
focus: me.SomeMethod, //
}
};
}
}
break;
}
this.columns.push(column);
}, gridConfig);
return gridConfig.columns;
},
I want if I select in header combo, it will directly select in widget combo as well. Can anyone explain how to get this. Thanks in advance
So you basically need a combo box in your header, that changes record values - the fact that you have a widget column displaying a combo within the grid cells doesn't really matter here.
I think you were fairly close - but you were trying to define a "header" config and add the combo to its items - instead you just define items directly on the column:
columns: [{
text: 'Combo Test',
dataIndex: 'title',
items: [{
xtype: 'combobox',
width: '100%',
editable: false,
valueField: 'title',
displayField: 'title',
queryMode: 'local',
autoSelect: true,
store: {
data: [{
"id": "1",
"title": "Test1"
}, {
"id": "2",
"title": "Test2"
}, {
"id": "3",
"title": "Test3"
}]
},
listeners: {
select: function (combo, selectedRecord) {
//we could just get the value from the combo
var value = combo.getValue();
//or we could use the selectedRecord
//var value = selectedRecord.get('id');
//find the grid and get its store
var store = combo.up('grid').getStore();
//we are going to change many records, we dont want to fire off events for each one
store.beginUpdate();
store.each(function (rec) {
rec.set('title', value);
});
//finish "mass update" - this will now trigger any listeners for saving etc.
store.endUpdate();
//reset the combobox
combo.setValue('');
}
}
}],
},
The actual setting of values happens in the select listener as you were trying - the key is to loop through the records and call set on each one:
//find the grid and get its store
var store = combo.up('grid').getStore();
//we are going to change many records, we dont want to fire off events for each one
store.beginUpdate();
store.each(function (rec) {
rec.set('title', value);
});
//finish "mass update" - this will now trigger any listeners for saving etc.
store.endUpdate();
I have created a fiddle to show this working:
https://fiddle.sencha.com/#view/editor&fiddle/1r01
ExtJS 5
I have a grid and it has 3 columns (Id, Students,Selected Students). In column2 (Students), I have bind static data. When i click on any item of second column then this record should be added in column3 (Selected Students) in current record or row. I have one button also called (Add new item) used for creating new row dynamically.
Note - When i add a new row by clicking on Add new item button, then new row will be added and 3 column(Selected Students) value should be blank.
I have tried so much but didn't get solution. The main problem is that when i bind data in third column then it binds proper, but when i add a new row, it also shows in new record also but it should not be. If i clear store or combo item, then it removes from all rows instead of current record/row.
Ext.onReady(function () {
var comboStore1 = Ext.create('Ext.data.Store',
{
fields: ['text', 'id'],
data:
[
{ "text": "Value1", "id" :1 },
{ "text": "Value2", "id": 2 },
{ "text": "Value3", "id": 3 }
]
});
var comboStore2 = Ext.create('Ext.data.Store',
{
fields: ['text', 'id']
});
var gridStore = Ext.create('Ext.data.Store',
{
fields: ['id', 'students', 'selectedStudents'],
data:
[
{ "id" : 1},
]
});
var window = new Ext.Window({
id: 'grdWindow',
width: 400,
height: 200,
items: [
{
xtype: 'panel',
layout: 'fit',
renderTo: Ext.getBody(),
items: [
{
xtype: 'button',
text: 'Add New Item',
handler: function () {
var store = Ext.getCmp('grdSample').store;
var rec = {
id: 1,
students: '',
selectedStudents: ''
}
store.insert(store.length + 1, rec);
}
},
{
xtype: 'grid',
id: 'grdSample',
store: gridStore,
plugins: [
Ext.create('Ext.grid.plugin.CellEditing', {
clicksToEdit: 1
})
],
columns: [
{
header: 'id',
dataIndex: 'id'
},
{
header: 'Students',
dataIndex: 'students',
editor: {
xtype: 'combobox',
store: comboStore1,
displayField: 'text',
valueField: 'text',
queryMode: 'local',
listeners: {
select: function (combo, records) {
var rec = records[0].data;
}
}
}
},
{
header: 'Selected Students',
dataIndex: 'selectedStudents',
editor: {
xtype: 'combobox',
id: 'combo2',
store: comboStore2,
displayField: 'text',
valueField: 'id'
}
}
]
}
]
}]
}).show();
});
I have tried almost everything but still i didn't get any solution. In another way - How to insert a value in grid editor combo only in current row. (Another row should not be reflected). If another row is being reflected, then how to remove value before rendering from another row without reflecting other rows.
Well, I guess main problem is that you trying to change certain grid row editor component while it suppose to be same for all grid rows.
The main problem is that when i bind data in third column then it binds proper, but when i add a new row, it also shows in new record also but it should not be. If i clear store or combo item, then it removes from all rows instead of current record/row.
It happens because all grid row editors use same store instance, comboStore2, and when you change its data you change it for all editors.
To create separate store for each editor you have to do something like this:
{
header: 'Selected Students',
dataIndex: 'selectedStudents',
editor: {
xtype: 'combobox',
id: 'combo2',
store: Ext.create('Ext.data.Store', {
fields: ['text', 'id']
}),
displayField: 'text',
valueField: 'id'
}
}
But than its become not trivial to select specific row editor component and its store.
I recommend you to take a look at Ext.grid.column.Widget as you can bind certain row (its record actually) to widget with its onWidgetAttach property.
Your second column is dummy.
You could directly use a tagfield component as the editor for your third column, which lets you select multiple values.
And you'll need a single store for the list of all students.
Oof that was a long title.
In my current project I have a grid that holds a set of workshop records. For each of these workshops there is a set of rates that apply specifically to the given workshop.
My goal is to display a combobox for each row that shows the rates specific to that work shop.
I've got a prototype that works for the most part up on sencha fiddle, but there's something off about how the selection values are being created:
Ext.define('Rates',{
extend: 'Ext.data.Store',
storeId: 'rates',
fields: [
'rateArray'
],
data:[
{
workshop: 'test workshop 1',
rateArray: {
rate1: {show: "yes", rate: "105", description: "Standard Registration"},
rate3: {show: "Yes", rate: "125", description: "Non-Member Rate"},
rate4: {show: "yes", rate: "44", description: "Price for SK tester"}
}
},
{
workshop: 'test workshop 2',
rateArray: {
rate1: {show: "yes", rate: "10", description: "Standard Registration"},
rate2: {show: "yes", rate: "25", description: "Non-Member Registration"}
}
}
]
});
Ext.define('MyGrid',{
extend: 'Ext.grid.Panel',
title: 'test combo box with unique values per row',
renderTo: Ext.getBody(),
columns:[
{
xtype: 'gridcolumn',
text: 'Name',
dataIndex: 'workshop',
flex: 1
},
{
xtype: 'widgetcolumn',
text: 'Price',
width: 200,
widget:{
xtype: 'combo',
store: [
// ['test','worked']
]
},
onWidgetAttach: function (column, widget, record){
var selections = [];
Ext.Object.each(record.get('rateArray'), function (rate, value, obj){
var desc = Ext.String.format("${0}: {1}", value.rate, value.description);
// according to the docs section on combobox stores that use 2 dimensional arrays
// I would think pushing it this way would make the display value of the combobox
// the description and the value stored the rate.
selections.push([rate, desc]);
});
console.log(selections);
widget.getStore().add(selections);
}
}
]
});
Ext.application({
name : 'Fiddle',
launch : function() {
var store = Ext.create('Rates');
Ext.create('MyGrid',{store: store});
}
});
In the grid widget that I'm using for the combobox I'm using the onWidgetAttach method to inspect the current row's record, assemble the rate data from the record into 2 dimensional array, and then setting that to the widget's store.
When I look at the sencha docs section on using a 2 dimensional array as the store, it states:
For a multi-dimensional array, the value in index 0 of each item will be assumed to be the combo valueField, while the value at index 1 is assumed to be the combo displayField.
Given that, I would expect the combo box to show the assembled description (e.g.
"$150: Standard Registration") and use the object key as the actual stored value (e.g. "rate1").
What I'm actually seeing is that the display value is the rate and I'm not sure how sencha generates the combobox selections to see how the selection is being rendered out.
Is my assumption about how the 2-dimensionally array gets converted to the store wrong?
Well, your question is suffering from the XY problem. Because what you really want to do is the following:
You want to create a decent store for your combo, using a well-defined model with the meaningful column names you already have in "rateArray", then you define displayField and valueField accordingly, and in onWidgetAttach, just stuff the "rateArray" object into that store using setData.
Sth. along the lines of
xtype: 'widgetcolumn',
text: 'Price',
width: 200,
widget:{
xtype: 'combo',
store: Ext.create('Ext.data.Store',{
fields:['rate','description','show']
filters:[{property:'show',value:"yes"}]
}),
displayField:'description',
valueField:'rate',
onWidgetAttach: function (column, widget, record){
widget.getStore().setData(record.get("rateArray"));
}
},
I am trying to populate a combobox with a list of Project names. I am able to successfully get all Project names, but I cannot seem to figure out how to add them as a custom set of data to a combobox. I have looked into using the other types of comboboxes (Iteration, Portfolio, Attribute, etc), but they don't seem to have the capabilities to add custom data to their drop down list (unless I am mistaken). Here is the code that I am using for my combo box:
this.down = this.add({
xtype: 'rallycombobox',
storeConfig: [{
model: 'Project',
autoLoad: true,
fieldLabel: 'Projects:',
data: this.project_names,
width: field_width
}]
});
When trying to run with this code, I get a "Uncaught TypeError: Cannot call method 'getProxy' of undefined. I cannot figure out how to get it to work. I have also tried it with the following:
this.down = this.add({
xtype: 'rallycombobox',
model: 'Project',
fieldLabel: 'Projects:',
data: this.project_names,
width: field_width
});
I still end up with the same error. Can anyone help me with what I am doing wrong? Thanks!
If you already have a list of Projects in hand that you'd like to use in a ComboBox, instead of a Rally ComboBox I'd recommend just using the Ext ComboBox. The Rally ComboBox is designed to populate its store by querying the data from rally - thus the getProxyerror you are seeing when trying to mix and match the Rally WSAPI store with local data.
The setup might look something like the following.
// The data store containing the list of Projects
var projectStore = Ext.create('Ext.data.Store', {
fields: ['_ref', 'Name'],
data : [
{"_ref": "/project/12345678910", "Name": "Project 1"},
{"_ref": "/project/12345678911", "Name": "Project 2"},
{"_ref": "/project/12345678912", "Name": "Project 3"}
//...
]
});
// Create the combo box, attached to the Projects data store
this.projectSelector = Ext.create('Ext.form.ComboBox', {
fieldLabel: 'Choose Project',
store: projectStore,
queryMode: 'local',
displayField: 'Name',
valueField: '_ref',
listeners:{
scope: this,
select: function(combobox) {
// Do stuff here
console.log('Ref of Project Selected: ' + this.projectSelector.getValue());
}
}
});
this.down('#projectSelectorContainer').add(this.projectSelector);
Hopefully this is helpful. Let us know if there's follow-on questions.
This might help you:
Ext.define('CustomApp', {
extend: 'Rally.app.App',
componentCls: 'app',
launch: function() {
//Write app code here
var projectStore = Ext.create('Rally.data.WsapiDataStore',{
model: 'project',
fetch: ['Name','ObjectID'],
autoLoad: true,
// filters:[{
// property:'ObjectID',
// operator:'=',
// value: __PROJECT_OID__
// }],
listeners:{
load: function(store,records,success){
this._updateCombo(store);
},
scope: this
}
});
console.log('/project/',__PROJECT_OID__);
},
_loadCombo: function(myStore){
this._myCombo = Ext.create('Ext.form.ComboBox',{
fieldLabel: 'Choose Project',
store: myStore,
queryMode: 'remote',
displayField: 'Name',
valueField: 'Name',
listeners: {
select: function(combobox,records){
console.log(records[0]["data"]["Name"]);
}
},
scope:this
});
this.add(this._myCombo);
},
_updateCombo: function(myStore){
if(this._myCombo === undefined){
this._loadCombo(myStore);
}else{
this._myCombo.clearValue();
}
}
});
I'm seeing an issue with a combobox where I have a listener for the 'change' event. When the event fires it runs a function that filters a store that powers another combobox to filter the values that are available in the 2nd combobox.
The idea is that when you pick from a short list in the first combobox, it pares down the choices in the second combobox.
When the form loads, you can click the second combobox and see all the choices, that works great. When you then select something in the first combobox and then click the second combobox again, you see the appropriate shortened list but it's grayed out and the 'loading...' thing just spins and will never go away.
If you load the form and pick something in the first combobox and then click the second combobox it will filter and show fine but you run into the issue of the loading problem I described above if you try to change your selection in the first box and click the second combobox again.
Please see the code below, I have this setup working on another screen and it doesn't seem to have this issue.
I've got an ext store created like the following:
var comboBreaker = Ext.create('Ext.data.Store', {
autoLoad: false,
remoteSort: true,
remoteFilter: true,
fields: [{
name: 'id',
mapping: 'item_id',
type: 'int',
useNull: false},
'item_display_number','item_name', 'line_item_type_id', 'item_description'
],
proxy:{
type:'ajax',
url: '/invoicer/data/getlineitems',
reader: {
type: 'json',
successProperty: 'success',
root: 'results',
totalProperty: 'totalCount'
},
sorters:[{
property:'item_display_number',
direction:'ASC'
}]
}
});
This store powers a combobox, like so:
Ext.define('Writer.Form', {
extend: 'Ext.form.Panel',
alias: 'widget.writerform',
requires: ['Ext.form.field.Text'],
initComponent: function(){
this.addEvents('create');
Ext.apply(this, {
activeRecord: null,
frame: true,
title: 'Line Item',
id: 'writerform',
fieldDefaults: {
anchor: '100%',
labelAlign: 'right'
},
items: [{
xtype: 'combobox',
fieldLabel: 'Item #',
name: 'item_number',
store: comboBreaker,
displayField: 'item_display_number',
valueField: 'id',
allowBlank: false,
forceSelection: true
},{
xtype: 'combobox',
fieldLabel: 'Item Type',
name: 'item_type',
id: 'item_type',
displayField: 'line_item_type',
valueField: 'id',
store: invoicer_lineItemTypeStore,
forceSelection: true,
labelWidth: 75,
width: 200,
listeners: {
change: {
fn: function() {
itemNumberFilter(comboBreaker);
}
}
}
}]
});
The itemNumberFilter() function takes a store and does filtering on it, here is that code:
function itemNumberFilter( store ) {
var id = Ext.getCmp('item_type').getValue();
store.remoteFilter = false;
store.clearFilter();
if ( id ) {
store.filter('line_item_type_id', id);
}
store.remoteFilter = true;
store.removeAll();
store.load({
scope: this,
callback: function( records ) {
console.log('Loaded records!');
console.log(records);
}
});
}
I see the logged out records every time I change my selection in the first combobox and I can 'see' the results in the second combobox but they're always grayed out with the 'loading..' GIF showing.
Edit: Video example: http://screencast.com/t/cUSHyFE6FIV
Edit: I believe this is the solution:
lastQuery: '',
listeners: {
beforequery: {
fn: function(query) {
delete this.lastQuery;
}
}
}
Adding this to the combobox config fixes the issue.
Edit2: I ran into a second bug introduced by this, it was fixed by adding:
this.clearValue();
to the beforequery function (above delete this.lastQuery). This clears the value of the combobox each time the drop down arrow is clicked.
Let's say you select item x in combo_1 and then item a in the pared down list in combo_2. You then change the selection in combo_1 to y, which then changes the list of items again in combo_2. Is a available in the new list in combo_2 that results from selecting item y in combo_1? Maybe it is an issue of trying to keep an item selected when it no longer exists in the list available to the combo.
Have you tried clearing the selection in combo_2 before applying the filter?
You can dynamically load the store of the second combox box but be sure to set the second combox box to "local".