I have a combo like below.
Ext.create('Ext.form.ComboBox', {
fieldLabel: 'Label',
allowBlank: true,
maxLength: 50,
minChars: 10000,
name: 'txt',
id: 'txt',
store: states,
displayField: 'name',
selectOnFocus: false,
forceSelection: false,
typeAhead: false,
autoSelect: false,
queryMode: 'local',
triggerAction: 'all',
hideTrigger: true,
listeners: {
beforequery: function (record) {
record.query = new RegExp(record.query, 'i');
record.forceAll = false;
},
specialkey: function (f, e) {
if (e.getKey() == e.ENTER) {
doProcess();
}
}
},
renderTo: Ext.getBody()
});
My purpose to provide is building a textbox that remember history. I've searched and found this solution: You must use combo like textfield.
No problem so far.
But when I write something and select record from list that searched before, the next time combo selects it automatically while I write.
I'm not sure if I explained.
You can test it here: https://fiddle.sencha.com/#view/editor&fiddle/28tl
Regards.
You can set the trackOver boundlist config to false like so:
xtype: 'combo',
...
listConfig: {
trackOver: false
}
Fiddle: https://fiddle.sencha.com/#view/editor&fiddle/2945
Try with "tagfield". Check here
Hi I've solved my problem like below.
https://fiddle.sencha.com/#view/editor&fiddle/28tl
This example tells me more clear than my question.
Ext.application({
name: 'Fiddle',
launch: function () {
// The data store containing the list of states
var states = Ext.create('Ext.data.Store', {
fields: ['abbr', 'name'],
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.form.ComboBox', {
fieldLabel: 'Label',
allowBlank: true,
maxLength: 50,
minChars: 10000,
name: 'txt',
id: 'txt',
store: states,
displayField: 'name',
selectOnFocus: false,
forceSelection: false,
typeAhead: false,
autoSelect: false,
queryMode: 'local',
triggerAction: 'all',
hideTrigger: true,
enableKeyEvents: true
,
listConfig: {
listeners: {
itemclick: function (list, record) {
_iseFareIleSecildi = true;
},
highlightitem: function (view, node, eOpts) {
_iseKlavyeIleSecildi = true;
}
}
},
listeners: {
beforequery: function (record) {
record.query = new RegExp(record.query, 'i');
record.forceAll = false;
Ext.defer(function () {
secimiSifirla();
}, 30);
},
specialkey: function (f, e) {
if (e.getKey() == e.ENTER) {
console.log('action');
}
},
keyup: function (combo, e) {
if (e.getKey() == e.ENTER) {
console.log('action');
}
},
beforeselect: function (combo, record, index, eOpts) {
if (_iseFareIleSecildi) {
secimiSifirla();
return true;
} else {
if (_iseKlavyeIleSecildi) {
secimiSifirla();
return true;
} else {
return false;
}
}
}
},
renderTo: Ext.getBody()
});
}
});
var _iseFareIleSecildi = false;
var _iseKlavyeIleSecildi = false;
function secimiSifirla() {
_iseFareIleSecildi = false;
_iseKlavyeIleSecildi = false;
}
Regards.
Related
I am trying Extjs and I am trying this scenario: I have a combobox which will display the first level in a hierarchy by default. That is to say:
0001
0001.0002
0001.0002.0004
0001.0003
0005
First level would be 0001 and 0005. If I select 0001 it goes into the restapi and fetches 0001.0002 and 0001.0003. That behavior is working as expected. My problem is this: I have to show the fetched data in this very same combobox and to keep selected the item I chose first. What my combo is doing is loading the data, but unselecting everything. Here is what I did so far:
var store = Ext.create('mycomponents.store.mystore', {});
var selectedText = '';
var autoSelec = false;
Ext.define('mycomponents.view.myview', {
extend: 'Ext.container.Container',
id: 'myview',
alias: 'widget.newComponent',
xtype: 'myview',
items: [
{
xtype: 'combobox',
reference: 'levels',
publishes: 'value',
fieldLabel: 'Options',
displayField: 'val',
valueField: 'val',
queryMode: 'local',
lastQuery: '',
emptyText: 'Please select...',
anyMatch: true,
anchor: '-15',
store: store,
minChars: 0,
typeAhead: true,
triggerAction: 'all',
selectOnFocus:true,
typeAheadDelay: 100,
labelWidth: 100,
labelAlign: 'right',
width: 265,
pageSize: 0,
clearFilterOnBlur: true,
defaultValue: 0,
matchFieldWidth: false,
allowBlank: false,
forceSelection: true,
enableKeyEvents: true,
onTrigger2Click: function (args) {
this.select(this.getStore().getAt(0));
},
listeners: {
select: function (combo, record, eOpts) {
console.log('Select', combo, record, eOpts);
},
change: function (item, newValue, oldValue) {
if (!autoSelec && newValue !== oldValue && !store.isLoading() && item.selection) {
if (newValue) {
selectedText = newValue;
}
store.proxy.extraParams = {
sort: 'clave',
'filter[activo]': true,
'filter[idpadre]': item.selection.data.idelemento
};
store.load({
callback: function () {
var items = store.data.items;
if (items.length) {
console.log('MY STORE >>>', items);
}
autoSelec = true;
}
});
}
}
}
}
],
initComponent: function () {
this.callParent(arguments);
var that = this;
}
});
How can I set the previous chosen item as the selectt item after the store load and therefore not to allow the reload of the store?
I found a solution after of spent all day long of searching and reading. Maybe this could sound very naive, but I'm starting with Extjs.
Here is the solution:
var items = store.data.items;
store.insert(0, mypreviousElement);
item.setValue(items[0]);
item.focus();
from here, item is my combo... this is a callback after store.load, hope this might help.
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.
I have a combobox for State that successfully filters in Rally. The code below works. I want to add an enhancement and have the combobox default to 'In Progress'. I added defaultValue but it has no effect. Thanks for your help.
Rally.onReady(function() {
Ext.define('Rally.example.CustomStoreGrid', {
extend: 'Rally.app.App',
componentCls: 'app',
launch: function() {
Ext.create('Rally.data.wsapi.Store', {
model: 'defect',
autoLoad: true,
limit: 1000,
pageSize: 1000,
listeners: {
load: this._onDataLoaded,
scope: this
},
fetch: ['FormattedID', 'Name', 'Severity', 'State', 'InProgressDate', 'c_PlannedDeliveryVersion']
});
},
_onSelect: function() {
var grid = this.down('rallygrid'), store = grid.getStore();
store.clearFilter(true);
store.filter(this._getStateFilter());
},
_getStateFilter: function() {
return {
property: 'State',
operator: '=',
defaultValue: 'In Progress',
value: this.down('#priorityComboBox').getValue()
};
},
_onDataLoaded: function(store, data) {
var records = _.map(data, function(record) {
//Perform custom actions with the data here
//Calculations, etc.
return Ext.apply({
// Age: Math.round(((new Date() - record.get('InProgressDate')) / 86400000) * 10) / 10;
}, record.getData());
});
this.add({
xtype: 'rallyfieldvaluecombobox',
itemId: 'priorityComboBox',
fieldLabel: 'Filter by State:',
model: 'defect',
// multiSelect: true,
field: 'State',
listeners: {
select: this._onSelect,
// ready: this._onLoad,
scope: this
}
});
this.add({
xtype: 'rallygrid',
showPagingToolbar: false,
showRowActionsColumn: false,
editable: false,
store: Ext.create('Rally.data.custom.Store', {
limit: 1000,
pageSize: 1000,
data: records
}),
columnCfgs: [
{
xtype: 'templatecolumn',
text: 'ID',
dataIndex: 'FormattedID',
width: 100,
tpl: Ext.create('Rally.ui.renderer.template.FormattedIDTemplate')
},
{
text: 'Name',
dataIndex: 'Name',
flex: 1
},
{
text: 'Severity',
dataIndex: 'Severity'
},
{
text: 'State',
dataIndex: 'State'
},
{
text: 'Planned Delivery Version',
dataIndex: 'c_PlannedDeliveryVersion',
flex: 0.25
},
{
text: 'In Progress Date',
dataIndex: 'InProgressDate',
xtype: 'datecolumn',
format:'Y-m-d'
},
{
text: 'Age',
dataIndex: 'InProgressDate'
,
renderer: function(value) {
return Math.round(((new Date() - value) / 86400000) * 10) / 10;
}
}
]
});
}
});
Rally.launchApp('Rally.example.CustomStoreGrid', {
name: 'Custom Store Grid Example'
});
});
Using value config property sets the default value:
Ext.define('CustomApp', {
extend: 'Rally.app.App',
componentCls: 'app',
items:{ html:'App SDK 2.0rc3 Docs'},
launch: function() {
this.add({
xtype: 'rallyfieldvaluecombobox',
model: 'UserStory',
field: 'ScheduleState',
value: 'In-Progress'
});
}
});
I have a tree panel. Each node in the tree has a check box. When users check a node, I add the text of the node as an option to a combo box. This much works like a charm.
When users uncheck a node, I want to remove the corresponding option from the combo box. Sometimes it removes, and sometimes it does not. I have been pulling my hair out for days now. What am I doing wrong? Thanks.
Here is my the init function in my controller:
init: function () {
this.control({
"#problemsTree": {
load: this.selectFirstProblem,
select: this.showProblemDetail,
checkchange: this.handleCheckChange
},
"#run-problems-button": { click: this.runSelectedProblems },
"#stop-problems-button": { click: this.stopSelectedProblems }
});
}
Here is handleCheckChange function in the same controler:
toggleLogOption: function(record, isChecked) {
var logStore = Ext.StoreManager.lookup("logs-store");
if(isChecked && logStore.find("text", record.data.text) == -1) {
logStore.add(record)
} else if(!isChecked) {
logStore.remove(record)
}
logStore.sync();
},
handleCheckChange: function(node, isChecked) {
if(node.isLeaf()) {
var record = Ext.create("GiipIq.model.Log", {id: node.data.id, text: node.data.text});
this.toggleLogOption(record, isChecked);
} else {
node.cascadeBy(function(nd) {
nd.set("checked", isChecked);
if(nd.isLeaf()) {
var record = Ext.create("GiipIq.model.Log", {id: nd.data.id, text: nd.data.text});
this.toggleLogOption(record, isChecked);
}
},
this
);
}
},
Here is my Log combo:
Ext.define("GiipIq.view.Log", {
extend: "Ext.window.Window",
alias: "widget.logwindow",
titleAlign: "center",
closable: false,
maximizable: true,
draggable: false,
resizable: false,
overflowX: "hidden",
border: false,
layout: 'fit',
x: (Ext.getBody().getViewSize().width/2) + 2,
y: 0,
width: (Ext.getBody().getViewSize().width/2) - 5,
height: Ext.getBody().getViewSize().height/2,
initComponent: function () {
this.items = [{
xtype: "panel",
itemId: "logPanel",
title: "Live Logs ",
tools:[{
xtype:"combo",
width: 250,
emptyText: "Filter logs",
id: "logFilter",
store: Ext.create("GiipIq.store.Logs"),
queryMode: "local",
displayField: "text",
valueField: "id"
}]
}];
this.callParent(arguments);
}
});
Here is my Log store:
Ext.define("GiipIq.store.Logs", {
extend: "Ext.data.Store",
storeId:"logs-store",
model: "GiipIq.model.Log",
sorters: [{ property: "text", direction: "ASC" }]
});
Here is my Log model:
Ext.define("GiipIq.model.Log", {
extend: "Ext.data.Model",
idProperty: "text",
fields: [
{ name: "id", type: "string"},
{ name: "text", type: "string" }
],
proxy: {
type: "localstorage",
id: "proxy-key",
listeners: {
exception: function(proxy, response, operation, opts) {
if(typeof(operation.error) == "string") {
Ext.Msg.alert("Error", "Connection to server interrupted" + operation.error);
}
}
}
}
});
You always create new record even if you are trying to remove. The logic should rely on ids, they seem to be same in tree and combo, and when removing, you should try to find the record in combo by id and remove that. Create new record only if adding.
I have 2 combobox, when i click on second combobox the loading appears and it remain there till I click on list item. I dont want loading to appear on second combo.
I have 2 combobox, when i click on second combobox the loading appears and it remain there till I click on list item. I dont want loading to appear on second combo.
var UnitPanel = Ext.create('Ext.panel.Panel', {
itemId:'dsUnitPanel',
border:0,
items:[UnitGrid,{
xtype:'combobox',
tpl: '<tpl for="."><div class="x-boundlist-item" >{name} [{freeSize} GB Free] </div></tpl>',
style:'margin:10px;',
fieldLabel: 'A Group(*)',
editable:false,
bodyStyle:'padding-left:10px;',
store: dsAStore,
valueField:'name',
displayField:'name',
//forceSelection: true,
multiSelect: false,
name: 'txtMode',
id:'dsVolumeGroupId',
queryMode: 'local',
triggerAction: 'all',
emptyText:'Select A Group',
listeners: {
select: function(combo, record, index) {
this.getStore().each(function(r){
if(combo.getValue() == r.data['name'])
{
selectedDsVg = combo.getValue();
selectedDsVgFreeSize = r.data['freeSize'];
}
});
} ,
'focus':function()
{
if(selectedDsWizardIndex == null)
{
Ext.MessageBox.alert('Error', 'Please select at least one Array',function(){
enableTabIndexing();
});
}
}
}
},
{
xtype:'combobox',
style:'margin:10px;',
fieldLabel: 'B Group(*)',
editable:false,
bodyStyle:'padding-left:10px;',
loadMask: false,
store: BGroupStore,
valueField:'value',
displayField:'name',
multiSelect: false,
name: 'dsBGroupId',
id:'dsBGroupId',
queryMode: 'local',
triggerAction: 'all',
//disabled:true,
emptyText:'Select B Group',
listeners: {
select: function(combo, record, index) {
//store.on('load', function () { this.getPicker().setLoading(false); }, this);
this.getStore().loadMask.hide();
this.getStore().each(function(r){
if(combo.getValue() == r.data['value'])
{
alert('Select');
bGroupName = r.data['name'];
}
});
},
'focus':function()
{
if(selectedDsWizardIndex == null)
{
Ext.MessageBox.alert('Error', 'Please select at least one',function(){
enableTabIndexing();
});
}
}
}
}
Please suggest.
You should define a listConfig like:
listConfig: {
loadingText: null,
loadMask: false
}