I need to set a ban on editing the text field in Ext.window.Window, provided that the value of the drop-down list is set to Postponed.
I'm trying to do this in the filterCombo function with:
var inp = this.up ('window'). down ('# MyTextField');
inp.disable ();
but in the console I get the error:
TypeError: this.up is not a function
What am I doing wrong?
Below is my code:
var store = Ext.create('Ext.data.Store', {
fields: ['order', 'id', 'name'],
storeId: 'DoubleBookStore',
data : [
{"id": 23, name: "New", order_install: 1},
{"id": 24, name: "In Work", order_install: 2},
{"id": 29, name: "Postponed", order_install: 3},
{"id": 34, name: "Shipped", order_install: 4},
{"id": 31, name: "In_transit", order_install: 5}
]
});
function filterCombo(combobox, records) {
if(records.data.name == 'Postponed'){
var inp = this.up('window').down('#MyTextField');
console.log(inp);
inp.disable();
}
index = records.data.order_install;
store = combobox.getStore();
store.clearFilter();
store.filterBy(
function(record) {
if ((record.internalId == index - 1) || (record.internalId == index) || (record.internalId == index + 1)) {
return true;
} else {
return false;
}
}
);
};
var window = Ext.create('Ext.window.Window', {
title: 'Приложение',
width: 300,
height: 200,
items:[{
xtype: 'combobox',
fieldLabel: 'Status',
name: 'status',
store: store,
valueField: 'id',
displayField: 'name',
typeAhead: true,
queryMode: 'local',
value: 24,
listeners: {
select : function(combo, records) {
filterCombo(combo, records);
}
}
},
{
xtype: 'textfield',
fieldLabel: 'Ваше имя:',
itemId:'MyTextField',
name: 'name'
}]
});
window.show();
You cant use "this" outside the scope of the select function, you are already passing "this" as the parameter "combobox", so use it like this:
function filterCombo(combobox, records) {
var inp = combobox.up('window').down('#MyTextField');
if(records.data.name == 'Postponed'){
inp.disable();
} else {
inp.enable();
}
...
When you define the filterCombo method as you define it takes this as global scope. Thats why there is no this.up as this here is global.
To make your code working you need to pass the scope when calling your function, just replace
listeners: {
select : function(combo, records) {
filterCombo(combo, records);
}
}
with
listeners: {
select : function(combo, records) {
filterCombo.apply(this,[combo, records]);
}
}
Notice the use of apply to alter the behavior of this in your method.
Solution:
function filterCombo(combobox, records) {
if (records.data.name == 'Postponed'){
var inp = combobox.up('window').getComponent('MyTextField');
console.log(inp);
inp.disable();
}
...
});
Explanation:
What you want to do is to get reference to your textfield and then disable it.
your texfield config uses itemId, so you must use texfield's container getComponent() method
to get textfield container use combobox.up('window'), not this.up('window')
Related
I am trying to get the number of items in the combo box so that I can make the first value by default visible in the combo box using the getCount() method but I see it always return 0 so cannot get the first item to be displayed in the combo box.
Code for my combo box is as shown below:
Ext.define('something....', {
controller: 'some Controller',
initComponent: function() {
var me,
me = this;
me.items = [{
xtype: 'form',
items: [{
xtype: 'combo',
itemId: 'nameId',
name:'nameId',
labelAlign: 'top',
fieldLabel: 'Name',
store: me._getNames(),
//disabled:some condition?true:false,//doesn't gray out combo
valueField:'dataId',
displayField: 'firstName',
editable: false,
listeners:{
afterrender: function(combo,component) {
var combo = me.down('#nameId');
var nameStore = combo.getStore();
var setFirstRecord = function(combo){
var nameStore = combo.getStore();
if(nameStore.getCount() === 1){
combo.setValue(nameStore.getAt(0));
}
}
if(nameStore.isLoaded() === false){
nameStore.on('load', function(nameStore){
setFirstRecord(combo);
},this,{
single:true
});
}else{
setFirstRecord(nameStore);
}
},
}
}]
}];
}
Code for the store is as below:
_getNames: function (){
var nameStore = Ext.create('Ext.data.Store', {
autoLoad: true,
proxy: {
type: 'ajax',
url: 'name.json',
reader: {
type: 'json',
rootProperty:'items',
transform: function (data) {
var data = {
items: [{
dataId: data[0].dataId,
firstName: data[0].name.firstName,
nameDetails: data[0].nameDetails
}]
}
return data;
}
},
},
fields: ['dataId', 'firstName','nameDetails']
});
return namesStore;
}
})
The result returned from the api to populate the store is as follows:
[
{
"dataId":1,
"name":{
"dataId":1,
"firstName":"Julie",
"code":"10",
"connectionList":[
"EMAIL"
]
},
"nameDetails":{
"EMAIL":{
"dataId":1,
"detail":"EMAIL"
}
}
}
]
Any suggestions on what's missing would be great!
I am written that example for you in Sencha Fiddle: https://fiddle.sencha.com/#view/editor&fiddle/3cdl
That solve your problem:
combo.getStore().on("load",
function (store, records, successful, operation, eOpts) {
if (store.getData().length > 0)
combo.setValue(store.getData().get(0).getData().id)
},
this
)
You must check if store is loaded or not and write appropriate code:
...
...
xtype: 'combo',
itemId: 'nameId',
name: 'nameId',
labelAlign: 'top',
fieldLabel: 'Name',
store: this._getNames(),
valueField: 'dataId',
displayField: 'firstName',
editable: false,
listeners: {
afterrender: function (combo) {
var store = combo.getStore();
var setFirstRecord = function (combo) {
var store = combo.getStore();
if (store.getCount() === 1) {
combo.setValue(store.getAt(0));
}
}
if (store.isLoaded() === false) {
store.on('load', function (store) {
setFirstRecord(combo);
}, this, {
single: true
});
} else {
setFirstRecord(combo);
}
}
}
...
...
When I remove the second line of data, a field on the first line appears undefined, that is, unable to execute the template:
{
field: "professionLevel",
title: '<#spring.message "技能等级"/>',
width: 120,
template: function (dataItem) { //meaning of the template: Just convert English to Chinese,
for (var i = 0; i < professionLevelData.length; i++) {
if (professionLevelData[i].value === dataItem.professionLevel) {
return dataItem.professionLevel = professionLevelData[i].meaning;
}
}
}
}
I think you're doing something else wrong. With the code you provided I cant salvage enough to reproduce the problem so I will present you with a simple working case (similar to your template logic):
var data = [
{id: 2, name: "John Doe", age: 33},
{id: 1, name: "Jane Doe", age: 30},
{id: 3, name: "Bob Doe", age: 22}
];
var translate = [
{value: 1, translate: "traslate 1"},
{value: 2, translate: "traslate 2"},
{value: 3, translate: "traslate 3"}
];
$("#grid").kendoGrid({
columns: [
{
field: "name",
template: function (dataItem) {
var returnValue = dataItem.name;
for (var i = 0; i < translate.length; i++) {
if (dataItem.id === translate[i].value) {
returnValue = translate[i].translate;
}
}
return returnValue;
}
},
{field: "age"},
{command: "destroy"}
],
dataSource: {
data: data,
schema: {
model: {id: "id"}
}
},
editable: true,
remove: function (e) {
console.log("Removing", e.model.name);
}
});
Example: Translate example
If this doesn't solve your problem please expand the question with relevant data.
PS. With return dataItem.professionLevel = professionLevelData[i].meaning; you are updating grids data source, are you sure you want to update it? Or just show meaning in table? In that case just return professionLevelData[i].meaning;
I am using selectize to provide inline cell editing in slickgrid. I am able to load this component within cell. But when dropdown options container pops up and it goes beyond the slickgrid viewport, dropdown options container is getting truncated by slickgrid boundary. It should come over the grid. How can I bring the dropdown options container to the top.
var grid;
var columns = [
{ id: 'title', name: 'Title', field: 'title' },
{ id: 'duration', name: 'Duration', field: 'duration' },
{ id: '%', name: '% Complete', field: 'percentComplete' },
{ id: 'start', name: 'Start', field: 'start' },
{ id: 'finish', name: 'Finish', field: 'finish' },
{
id: 'effort-driven',
name: 'Effort Driven',
field: 'effortDriven',
editor: IEditor
},
];
var options = {
enableCellNavigation: true,
enableColumnReorder: false,
editable: true,
autoHeight: true
};
function IEditor(args) {
var selectElement = $('<input type="text"/>');
args.container.append(selectElement[0]);
selectElement.selectize({
create: false,
maxElements: 1,
options: [
{
name: 'A',
value: 'a'
},
{
name: 'B',
value: 'b'
},
{
name: 'C',
value: 'c'
},
{
name: 'D',
value: 'd'
},
{
name: 'E',
value: 'e'
},
{
name: 'F',
value: 'f'
},
],
labelField: 'name',
valueField: 'value'
});
/*********** REQUIRED METHODS ***********/
this.destroy = function() {
// remove all data, events & dom elements created in the constructor
};
this.focus = function() {
// set the focus on the main input control (if any)
};
this.isValueChanged = function() {
// return true if the value(s) being edited by the user has/have been changed
return false;
};
this.serializeValue = function() {
return '';
};
this.loadValue = function(item) {
};
this.applyValue = function(item, state) {
};
this.validate = function() {
return { valid: false, msg: 'This field is required' };
};
}
$(function() {
var data = [];
for (var i = 0; i < 3; i++) {
data[i] = {
title: 'Task ' + i,
duration: '5 days',
percentComplete: Math.round(Math.random() * 100),
start: '01/01/2009',
finish: '01/05/2009',
effortDriven: i % 5 == 0,
};
}
grid = new Slick.Grid('#myGrid', data, columns, options);
grid.init();
});
I have added selectize drop down in Effort Driven column in this plunker
I used to use chosen as my enhanced select but I ran into exactly this problem, and it wasn't solvable due to the HTML it used.
I had to jump ship to Select2. There are examples for this here - check out 'Select2 javascript drop-down editor' and 'Select2 Multiselect javascript drop-down editor'.
Make sure your z-index is bigger than the ones SlickGrid uses. If I remember correctly SlickGrid's highest one was 11 or 12, so with a 13 you should be good to go. Also check the overflow of the cells' css classes; it might happen that your context menu is simply cut off.
I am trying display the selected text of a picker field in a textfield in sencha touch 2.1.
I can't see any wrong in my code but still not working. below is my code. Please provide some working solution.
{
xtype : 'textfield ',
id : 'PacingMode ',
style : 'background - color: #585858;',
top : '13.5%',
usePicker : true,
left : '20%',
width : '5%',
listeners : {
'focus' : function(a,e, eOpts) {
console.log("show caling");
document.activeElement.blur();
if (!this.picker) {
this.picker = Ext.Viewport.add({
xtype: 'picker',
id: 'pacingModePickerfield',
useTitles: true,
slots: [{
name: 'quantity',
title: 'Pacing Mode',
data: modelMgr.slotsdata1,
valueField: 'value',
}
],
doneButton: {
listeners: {
// when the done button is tapped, set the value
tap: function (button, event, eOpts) {
var sel = document.getElementById("pacingModePickerfield");
var text_value = sel.options[sel.selectedIndex].text;
Ext.getCmp('PacingMode').setValue(text_value);
}
}
}
});
}
this.picker.show();
},
change: function (a, e, newValue, eOpts) {
sendValueSetRequest(this.id);
},
}
You should use the framework to get the value from the picker:
tap: function(button, event, eOpts) {
var val = Ext.getCmp("pacingModePickerfield").getValues().quantity;
Ext.getCmp('PacingMode').setValue(val);
}
Try this.
var thePicker = new Ext.Picker({
slots: [
{
name : 'limit_speed',
title: 'Speed',
data : [
{text: '50 KB/s', value: 50},
{text: '100 KB/s', value: 100},
{text: '200 KB/s', value: 200},
{text: '300 KB/s', value: 300}
]
}
],
listeners: {
change: function(picker, value, eOpts) {
alert(value.limit_speed);
}
}
});
This is my working code:
doneButton : {
listeners : {
tap : function(button,event,eOpts) {
var selectedUpperSensorValue = Ext.getCmp('upperSensorPickerfield').getValue()['Upper Sensor'];
sendSetPendingRequest("UpperSensor",selectedUpperSensorValue);
}
}
}
So I posted this last week to the ExtJS forums, but no one has responded and I'm going a bit crazy trying to figure it out:
I'm fairly new to ExtJS (just learned it last week for work), but I've been working with other JavaScript libraries for quite some time now. I'm making a custom control for editing a list of attributes (currently populated by a JSON request). I'm using PropertyGrid's with custom GridEditor's (created by extending various Ext.form fields). All of my custom fields work except one, which is a repeating value editor. Basically the field is going to be passed a simple 2d key/value pair array by the JSON request, which it displays in an EditorGridPanel (inside of a Ext.Window that I've created).
Here is the section of the JSON request that defines the repeating value editor:
{
key: 'Repeating',
type: 'repeating',
category: 'Category A',
options: {
dataArray: [
{key: 'key A', value: 'value A'},
{key: 'key B', value: 'value B'},
{key: 'key C', value: 'value C'}
]
}
}
The key is the name for the field (displayed on the left column of the PropertyGrid).
The type tells the function which creates all of the grid editors what type of custom editor to use.
The category is used to determine which PropertyGrid the GridEditor is added to (I have multiple PropertyGird's, all contained in a Panel with layout: 'acordion').
Anything in options is added to the extended Ext.form field when it is created.
So dataArray is attached to my repeating value editor for setting up the initial key/value pairs and to store the array passed back to the GridEditor by the Ext.Window used for editing it.
After some experimenting I decided to use a TriggerField as the GridEditor for my repeating value type. Here is the code for the definition of the repeating value field:
Ext.form.customFields = {
'repeating': Ext.extend(Ext.form.TriggerField, {
triggerClass: 'x-form-edit-trigger',
enableKeyEvents: true
})
};
And here is the code that sets it up:
Ext.form.customFields['repeating'] = Ext.extend(Ext.form.customFields['repeating'], {
onTriggerClick: function()
{
this.editorWindow.show();
},
listeners: {
'render': function(field)
{
field.editorWindow = new Ext.MultiSelectWindow({
data: field.dataArray,
parent: field
});
},
'keydown': function(field, event)
{
event.stopEvent();
},
'beforerender': function()
{
for (i in this.opt) {
if (i != 'store') {
this[i] = this.opt[i];
}
else {
this.store.loadData(this.opt.store);
}
}
if (this.regex != undefined) {
this.validator = function(value)
{
return this.regex.test(value);
};
}
}
}
});
And finally, here is the code for the custom editor window:
Ext.MultiSelectWindow = function(args)
{
var obj = this;
obj.args = args;
obj.KeyValue = new Ext.data.Record.create([{
name: 'key'
}, {
name: 'value'
}]);
obj.gridStore = new Ext.data.Store({
data: obj.args.data,
reader: new Ext.data.JsonReader({}, obj.KeyValue),
autoLoad: true
});
obj.cm = new Ext.grid.ColumnModel([{
id: 'key',
header: "Key",
dataIndex: 'key',
editor: new Ext.form.TextField({
allowBlank: false
}),
hideable: false,
sortable: false,
menuDisabled: true,
css: 'font-weight: bold;'
}, {
id: 'value',
header: "Value",
dataIndex: 'value',
editor: new Ext.form.TextField({}),
hideable: false,
sortable: false,
menuDisabled: true
}]);
obj.gridEditor = new Ext.grid.EditorGridPanel({
cm: obj.cm,
height: 280,
store: obj.gridStore,
autoExpandColumn: 'value',
listeners: {
'render': function()
{
// set up local aliases
obj.a = new Array();
obj.a.grid = obj.gridEditor;
obj.a.store = obj.a.grid.getStore();
obj.a.sel = obj.a.grid.getSelectionModel();
}
},
bbar: [{
text: 'Add',
cls: 'x-btn-text-icon',
icon: '/lib/images/add.png',
listeners: {
'click': function()
{
var kv = new obj.KeyValue({
key: '',
value: ''
});
var row = obj.a.store.data.items.length;
obj.a.grid.stopEditing();
obj.a.store.insert(row, kv);
obj.a.grid.startEditing(row, 0);
}
}
}, {
text: 'Delete',
cls: 'x-btn-text-icon',
icon: '/lib/images/delete.png',
listeners: {
'click': function()
{
if (obj.a.sel.selection)
obj.a.store.remove(obj.a.sel.selection.record);
}
}
}]
});
obj.panelAll = new Ext.Panel({
border: false,
layout: 'absolute',
items: [new Ext.Panel({
width: 250,
border: false,
x: 0,
y: 0,
items: obj.gridEditor
}), new Ext.Panel({
border: false,
x: 254,
y: 0,
items: [new Ext.Button({
cls: 'x-btn-icon-side',
icon: '/lib/images/arrow_up.png',
listeners: {
'click': function()
{
if (obj.a.sel.selection) {
var row = obj.a.sel.selection.cell[0];
var rec = obj.a.store.getAt(row);
if (row >= 1) {
obj.a.store.remove(rec);
obj.a.store.insert(row - 1, rec);
obj.a.grid.startEditing(row - 1, 0);
}
}
}
}
}), new Ext.Button({
cls: 'x-btn-icon-side',
icon: '/lib/images/arrow_down.png',
listeners: {
'click': function()
{
if (obj.a.sel.selection) {
var row = obj.a.sel.selection.cell[0];
var rec = obj.a.store.getAt(row);
var len = obj.a.store.data.items.length;
if (row < len - 1) {
obj.a.store.remove(rec);
obj.a.store.insert(row + 1, rec);
obj.a.grid.startEditing(row + 1, 0);
}
}
}
}
})]
})]
});
obj.win = new Ext.Window({
title: 'Repeating Value Editor',
layout: 'fit',
closeAction: 'hide',
border: false,
items: obj.panelAll,
width: 300,
height: 350,
resizable: false,
shadow: false,
buttonAlign: 'left',
buttons: [{
text: 'OK',
handler: function()
{
// reset the repeating field data array
obj.args.parent.dataArray = [];
for (r in obj.a.store.data.items)
obj.args.parent.dataArray[r] = obj.a.store.data.items[r].data;
obj.args.parent.setRawValue(attrValueToString(obj.args.parent.dataArray));
obj.win.hide();
}
}, {
text: 'Cancel',
handler: function()
{
obj.win.hide();
}
}]
});
obj.show = function()
{
obj.win.show();
obj.a.store.loadData(obj.args.parent.dataArray);
}
}
Now for my problem: all of this works fine, except for the 7th line of the window's 'OK' button handler ( obj.args.parent.setRawValue(attrValueToString(obj.args.parent.dataArray)); ).
obj is a self-alias.
obj.args.parent is an alias for the field that opened the repeating value editor window.
attrValueToString() is a function that takes in a 2d array and converts it to a string with special formatting so it can be displayed in a readable, meaningful manner in the TriggerField's textbox.
The data is loaded back into the field's dataArray variable and if you open the editor again, it will have the new data included in the view. I can't, however, manage to get any sort of value to be displayed in the TriggerField after it has been created. I have tried both obj.args.parent.setValue('abc') and obj.args.parent.setRawValue('abc') . No exception is thrown, yet the value displayed in the TriggerField does not change. I even tried creating a custom function for setting the value from within the TriggerField - something like this:
Ext.form.customFields['repeating'] = Ext.extend(Ext.form.customFields['repeating'], {
setFieldValue: function(value){
this.setValue(value);
}
});
This custom function works if called from within the TriggerField, but not when called from somewhere else (i.e. the editor window's 'OK' button handler). The function can be called successfuly from anywhere and does not produce any exceptions, however, it only sets the value correctly if called from within the TriggerField.
The custom field works perfectly when instantiated as a basic form field:
var sample = new Ext.form.customFields['repeating']({
renderTo: Ext.getBody(),
dataArray: [
{key: 'key A', value: 'value A'},
{key: 'key B', value: 'value B'},
{key: 'key C', value: 'value C'}
]
});
I have scoured the ExtJS API documentation and done every possible google search I can think of. I found a few forum posts that seem to be from people having a similar problem, but they never get a clear answer.
Any help with this matter would be most appreciated - thanks in advance!
I think you should use Ext.override for onTriggerClick handler function instead of redefining it in your superclass.
You also could set it right after triggerField creation (possibly in the 'render' event handler) by assigning it to a function name, i.e. trigger.onTriggerClick = somefunction.