Extjs listener out of the config - javascript

Hi extjs experts i have a simple question, but cant find the correct way to do it and was googling in for few days now. I have a listener inside config of extjs elements, it is easy to do it in this way, but how i could take the listener out of the config, and put it outside the config so config will be as minimum as possible and one listener can be used for many times just true the function call,
here is my code:
Ext.define("my.filter.TimeFilter",{
extend: "Ext.tab.Panel",
alias: "widget.myTimeFilter",
requires: ["my.filter.Filters"],
config: {
cls: 'ruban-filter-timefilter',
items: [
{
title: 'Time sections',
xtype: 'radiogroup',
fieldLabel: 'Time Selector',
items: [
{
boxLabel: '60 Mins',
name: 'unixMills',
inputValue: '3600000'
}, {
boxLabel: '8 Hours',
name: 'unixMills',
inputValue: '28800000'
}, {
boxLabel: '24 Hours',
name: 'unixMills',
inputValue: '86400000'
}, {
boxLabel: '7 Days',
name: 'unixMills',
inputValue: '604800000'
}, {
boxLabel: '30 Days',
name: 'unixMills',
inputValue: '2592000000'
}
],
listeners: {
change: function (field, newValue, oldValue) {
var endTime = new Date().getTime();
var startTime = endTime - newValue['unixMills'];
console.log("StartTime: " + startTime);
console.log("EndTime: " + endTime);
}
}
]
},
constructor: function(config){
this.callParent(arguments);
}
});
so i believe it should go after constructor as separate function or as listener itself, but i dont know, not so well familiar with js and extjs,
thanks everyone

You can add a listener outside of the config this way:
myElement.on('change', function () { ... }

There are quite a lot of possibilities.
If you have a lot of logic based on events, you can always create a controller and have them listen to the components. The controller documentation here should give you a pretty good idea of how to tie it together: http://docs.sencha.com/extjs/4.2.2/#!/api/Ext.app.Controller

Related

How to replace all events in FullCalendar library

I am creating a page using the FullCalendar.io library to display events on a webpage.
Now as the user navigates between between date ranges I want to load the events dynamically. Using the documentation I'm able to add the new events when the user presses the "next" button, however it simply appends the events to the existing events Object, what I want to do is remove any existing events and only display the new list. How can I do this?
You can view the functionality here on my CodePen.
HTML
<p>
<button id='prev'>prev</button>
<button id='next'>next</button>
</p>
<div id='calendar'></div>
JS
var calendar;
var eventsList = [{
id: '1',
title: 'event 1',
start: '2019-04-06'
},
{
id: '2',
title: 'event 2',
start: '2019-04-07'
},
{
id: '3',
title: 'event 3',
start: '2019-04-29'
},
{
id: '4',
title: 'event 4',
start: '2019-04-30'
}];
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
calendar = new FullCalendar.Calendar(calendarEl, {
plugins: [ 'interaction', 'dayGrid', 'timeGrid' ],
timeZone: 'UTC',
defaultView: 'dayGridMonth',
header: {
left: '',
center: 'title',
right: ''
},
editable: true,
events: eventsList
});
calendar.render();
});
document.getElementById('prev').addEventListener('click', function() {
calendar.prev(); // call method
});
document.getElementById('next').addEventListener('click', function() {
// replace existing list - this will doneby another function, hard coding for demo
eventsList = [{
id: '5',
title: 'event 5',
start: '2019-05-06'
},
{
id: '6',
title: 'event 6',
start: '2019-05-07'
},
{
id: '7',
title: 'event 7',
start: '2019-05-08'
},
{
id: '8',
title: 'event 7',
start: '2019-05-09'
}];
calendar.next(); // call method
calendar.addEventSource(eventsList);
//calendar.refetchEvents(); // using this instead of the line above does not work either, just loads original list
});
I misread the document, getEventSource returns an array of eventSource, so just simply point index and then remove should work.
calendar.getEventSources()[0].remove();
or if you have multiple resources,
calendar.getEventSources().forEach(eventSource => {
eventSource.remove()
})
Code below is mistaken, left for the record.
How about adding remove() before you add event source.
calendar.next(); // call method
calendar.getEventSources().remove();
calendar.addEventSource(eventsList);
//calendar.refetchEvents(); // this does not work either, just loads original list
https://fullcalendar.io/docs/Calendar-getEventSources
https://fullcalendar.io/docs/EventSource-remove

Setting an extjs 6 combobox's store data at runtime results in display error

I've got a prototype of a combo box where I'm trying to set the store data at runtime.
When I try to do this, the menu under the combobox doesn't render (or it renders so small you can't actually see it). It's here on sencha fiddle:
Ext.define('ComboBoxRates',{
extend: 'Ext.data.Store',
alias: 'store.rates',
storeId: 'ratescombo',
fields: ['rate', 'description', 'price' ]
});
Ext.define('ComboPanel',{
extend: 'Ext.panel.Panel',
title: 'Test',
renderTo: Ext.getBody(),
items:[
{
xtype: 'combobox',
editable: false,
displayField: 'description',
valueField: 'price',
}
]
});
Ext.application({
name : 'Fiddle',
launch : function() {
var data = [
{
description: "$105: Standard Registration",
price: "105",
rate: "rate1"
},
{
description: "$125: Non-Member Rate",
price: "125",
rate: "rate2"
},
{
description: "$44: Price for SK tester",
price: "44",
rate: "rate3"
},
{
description: "$11: Another price :O",
price: "11",
rate: "rate5"
}
];
var rates = Ext.create('ComboBoxRates');
rates.setData(data);
// Showing data is loaded into the store
console.group('directly from store instance');
rates.each(function (rate){
console.log(rate.getData());
});
console.groupEnd();
var panel = Ext.create('ComboPanel');
panel.down('combobox').setStore(rates);
// Showing that the data is definitely in the widget's store
console.group('from widget store');
panel.down('combobox').getStore().each(function (rate){
console.log(rate.getData());
});
console.groupEnd();
}
});
I know the data is loaded into the combobox's store (open the console log in the fiddle) so I'm not sure why it's not rendering correctly.
I know this seems silly in this context, but the prototype is logic extracted out of a grid's widget column where each row has different store data.
I also built a one-step-back prototype with the same structure but the same data is inlined in the store's definition and that works:
Ext.define('ComboBoxRates',{
extend: 'Ext.data.Store',
alias: 'store.rates',
storeId: 'ratescombo',
fields: ['rate', 'description', 'price' ],
data: [
{
description: "$105: Standard Registration",
price: "105",
rate: "rate1"
},
{
description: "$125: Non-Member Rate",
price: "125",
rate: "rate2"
},
{
description: "$44: Price for SK tester",
price: "44",
rate: "rate3"
},
{
description: "$11: Another price :O",
price: "11",
rate: "rate5"
}
]
});
Ext.define('ComboPanel',{
extend: 'Ext.panel.Panel',
title: 'Test',
renderTo: Ext.getBody(),
items:[
{
xtype: 'combobox',
editable: false,
displayField: 'description',
valueField: 'price',
}
]
});
Ext.application({
name : 'Fiddle',
launch : function() {
var rates = Ext.create('ComboBoxRates');
var panel = Ext.create('ComboPanel');
panel.down('combobox').setStore(rates);
}
});
I thought an updateLayout would resolve the issue but it doesn't.
Is there something wrong with my code? Is there some way of setting a combobox's values at runtime?
You are missing queryMode, use queryMode: 'local' in the combo.
Working example: https://fiddle.sencha.com/#fiddle/10al

Creating a simple Sencha component using a loop

How do we substitute hard-coded data with a for-loop in Sencha ExtJS?
Say, for example I've defined the following list:
Ext.application({
launch: function() {
Ext.create('Ext.List', {
fullscreen: true,
itemTpl: '{title}',
data: [{
title: 'Item 1'
}, {
title: 'Item 2'
}, {
title: 'Item 3'
}, {
title: 'Item 4'
}]
});
}
});
How to replace data to something like this:
Ext.application({
launch: function() {
Ext.create('Ext.List', {
fullscreen: true,
itemTpl: '{title}',
data: [
for(int i=0;i<5;i++){
{title: 'Item '+i},
}
]
});
}
});
This is really basic stuff - I'd recommend you familiarise yourself with the basic language constructs before investing time in a framework. There are several ways you could do this...
see: MDN: A re-introduction to Javascript
Simplest way, create your configuration data first and assign it to a variable:
Ext.application({
launch: function() {
var listData = [];
for(var i=0;i<5;i++)
listData.push({title: 'Item '+i});
Ext.create('Ext.List', {
// ...
data: listData
});
}
});
... or for those times when you're in the global execution scope and you don't want to pollute the window object with unnecessary variables - or just have an OCD over "one-liners" - you could take advantage of an inline function / closure:
Ext.create('Ext.List', {
// ...
data: (function(){
var data = [];
for(var i=0;i<5;i++)
data.push({title: 'Item '+i});
return data;
})()
});
... or on occasion I've used the following because I think it looks neater (but that's subjective):
Ext.create('Ext.List', {
// ...
data: Ext.Array.map(Array.apply(null, Array(5)), function(o,i){
return {title: 'Item '+i};
})
});

Why is the list showing no elements in sencha touch 2?

I am very much beginner to Sencha Touch. I want to display a static list to the screen. The code I tried is from sencha docs guides 'using list'. However, blank screen appears when compiled and run. Do I have to add the list to the Viewport? What am I missing? Please help.
My code is:
Ext.application({
launch: function () {
Ext.create('Ext.List', {
store: {
fields: ['name'],
data: [
{ name: 'A' },
{ name: 'B' },
{ name: 'C' },
{ name: 'D' }
]
},
itemTpl: '{name}'
});
}
});
May be this one help you
Ext.create('Ext.List', {
fullscreen: true,
itemTpl: '{title}',
data: [
{ title: 'Item 1' },
{ title: 'Item 2' },
{ title: 'Item 3' },
{ title: 'Item 4' }
]
});
Sorry! My bad. I made it with a little bit of work.
I just did this:
launch: function() {
var list = Ext.Create('Ext.List',{..
.....
.....
itemTpl = '{name}'
});
Ext.Viewport.add(list);
}

ExtJS - using a custom TriggerField as a GridEditor

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.

Categories