I am creating a itemclick event of chart series items in extjs
"mychart series": {
itemclick: function() {
alert('s');
}
}
The above function does not work.
Chart series is not a Component, and so the selector never matches. You need to relay Series events as if they were fired by the Chart itself, and match against the Chart:
Ext.define('My.Chart', {
extend: 'Ext.chart.Chart',
alias: 'widget.mychart',
initComponent: function() {
var me = this;
me.callParent();
me.series.each(function(s) {
// This will relay Series `itemclick` event
// as `seriesitemclick` fired on the Chart itself
me.relayEvents(s, ['itemclick'], 'series');
});
}
});
Ext.define('My.Controller', {
extend: 'Ext.app.Controller',
init: function() {
this.control({
mychart: {
seriesitemclick: this.onSeriesItemClick
}
});
},
onSeriesItemClick: function(item) {
var sprite = item.sprite,
series = item.series,
record = item.storeItem,
value = item.value;
...
}
});
Related
I have a store in ViewModel like:
Ext.define('MyApp.page.PageModel', {
extend: 'Ext.app.ViewModel',
//...
stores: {
Posts: {
model: //...
}
}
});
And a grid like:
Ext.define('MyApp.page.MainView', {
extend: 'Ext.panel.Panel',
//...
initComponent: function () {
var me = this;
//...
me.items = [
{
xtype: 'grid',
bind: {
store: '{Posts}'
},
columns: [ /* ... */ ],
viewConfig: {
getRowClass: function (record) {
//...
}
}
}
];
me.callParent(arguments);
}
});
How can I change grid view AFTER store load (in my case)?
I tried to use mon and addManagedListener methods in grid events (beforerender and viewready) and I tried to use on and addListener methods to store inside those grid events, but this solution is not working.
Does someone have any ideas?
I'm using override for Ext.view.AbstractView, just to clear emptyEl and viewEl before store load event
store.on('beforeload', function() {
me.clearEmptyEl();
me.clearViewEl();
});
Here is my complete override
Ext.define('Ext.overrides.view.AbstractView', {
override: 'Ext.view.AbstractView',
onBindStore: function(store, initial, propName) {
var me = this;
me.setMaskBind(store);
// After the oldStore (.store) has been unbound/bound,
// do the same for the old data source (.dataSource).
if (!initial && propName === 'store') {
// Block any refresh, since this means we're binding the store, which will kick off
// a refresh.
me.preventRefresh = true;
// Ensure we have the this.store reference set correctly.
me.store = store;
me.bindStore(store, false, 'dataSource');
me.preventRefresh = false;
}
store.on('beforeload', function() {
me.clearEmptyEl();
me.clearViewEl();
});
}
});
In ExtJS 6, a function setEmptyText is available on the grid that will do this for you:
initComponent: function () {
var me = this;
//...
me.callParent(arguments);
me.getStore().on('load', function() {
me.setEmptyText(...);
})
}
In ExtJS 5, you have to do on your own:
me.getStore().on('load', function() {
var emptyText = 'Test empty text';
me.getView().emptyText = '<div class="' + me.emptyCls + '">' + emptyText + '</div>';
me.getView().refresh();
})
Relevant fiddle, will load its store 3 seconds after rendering.
I have added buttons to a toolbar dynamically and now I am trying to add a listener that will replace the center window panel. I am having trouble hooking up the listener in viewcontroller.
This is how I have done it so far.
Can someone point me in the direction of the proper way to do this?
init: function () {
var dynamicMenu = [];
var me = this;
console.log(me);
console.log(this.view);
var myToolbar = this.view.down('toolbar');
console.log(myToolbar);
this.getViewModel().data.mainmenuv4store.load(function (records) {
console.log('hit load section');
Ext.each(records, function (record) {
//add individual button
var myButton = Ext.create('Ext.Button', {
text: record.get('text'),
iconCls: record.get('iconCls'),
iconAlign: 'left',
listeners: {
click: {
fn: function (event, target) {
me.selectMenuButton(event, target);
}
}
}
});
myButton.on({
click:
});
//add button to menu array
dynamicMenu.push(myButton);
});
//put this in storeLoad otherwise this section will be hit before loading everything
myToolbar.add(dynamicMenu);
});
},
selectMenuButton: function (event, target) {
Ext.Msg.alert('hi');
var targetCmp = Ext.get(target);
var id = targetCmp.getAttribute('text');
}
I changed my code to the below. Did I set this up efficiently?
Ext.define('ExtApplication1.controller.MainMenuV4ViewController', {
extend: 'Ext.app.ViewController',
alias: 'controller.mainmenuv4vc',
views: [
'ExtApplication1.view.main.MainMenuV4View'
],
init: function () {
var dynamicMenu = [];
var me = this;
console.log(me);
console.log(this.view);
var myToolbar = this.view.down('toolbar');
console.log(myToolbar);
this.getViewModel().data.mainmenuv4store.load(function (records) {
console.log('hit load section');
Ext.each(records, function (record) {
//add individual button
var myButton = Ext.create('Ext.Button', {
text: record.get('text'),
iconCls: record.get('iconCls'),
iconAlign: 'left',
handler: me.selectMenuButton, scope: me
});
//add button to menu array
dynamicMenu.push(myButton);
});
//put this in storeLoad otherwise this section will be hit before loading everything
myToolbar.add(dynamicMenu);
});
//listeners: {
// click: 'onProjectSelect'
// //click: {
// // fn: function (event, target) {
// // me.selectMenuButton(event, target);
// // }
// //}
//}
},
selectMenuButton: function (event, target) {
//Ext.Msg.alert('select menu button method hit');
console.log('select menu button section was hit')
console.log(event);
console.log(target);
}
Based on your comment on the question, it looks like you want a cleaner way to establish the listener. This is slightly cleaner:
Instead of listeners: {...}, use
handler: Ext.Function.bind(me.selectMenuButton, me)
In my code I use MVC architecture. My view Component looks like this:
Ext.define('calendar.view.event', {
extend: 'Ext.Component',
alias: 'widget.event',
renderTo: Ext.getBody(),
initComponent:function(){
this.addEvents('eventClick');
this.callParent(arguments);
},
afterRender: function() {
this.mon(this.el, 'click', this.eventClick, this); //mon( item, ename, [fn], [scope], [options] ) - zkratka pro addManagedListener.
this.callParent(arguments);
},
eventClick: function (ev, t) {
var height = this.getHeight();
this.fireEvent('eventClick', this, height, ev);
}
});
Im firing Event on click for controller which is like this:
Ext.define('calendar.controller.eventsChange', {
extend: 'Ext.app.Controller',
views: ['event'],
init: function () {
this.control({
'event': {
eventClick: function (callerObject) {
this.editEvent(callerObject)
}
}
});
},
editEvent: function (callerObject) { //oznaci jako editovatelny
callerObject.get
if(callerObject.hasCls('SpecEv') || callerObject.hasCls('activeEvent'))
{
if (callerObject.hasCls('activeEvent'))
{
callerObject.removeCls('activeEvent');
callerObject.addCls('SpecEv');
this.application.fireEvent('reRender');
}
else
{
console.log(callerObject);
callerObject.addCls('activeEvent');
callerObject.removeCls('SpecEv');
Ext.apply(callerObject, {
resizable: {
pinned:true,
dynamic:true
},
draggable: true,
});
callerObject.setLocalX(0);
var parentWidth = Ext.getCmp('SpecEv').getWidth();
callerObject.setWidth(parentWidth);
}
}
}
});
The problem comes when with
Ext.apply(callerObject, {resizable: {
pinned:true,
dynamic:true
},
draggable: true,
});
When console.log shows me the object after my apply, it says draggable:true and resizable:true. Does anyone know where the problem is?
Thanks for reponses.
It can't works, because your code only set configuration properties, which are handled only when component is initializing. So when you set these properties on already constructed object nothing happen. Component resizability and draggability will not be initialized automatically after setting these properties.
You can try use Ext.Component initResizable and initDraggable methods. But these methods are internal and undocumented.
callerObject.initResizable({
pinned:true,
dynamic:true
});
callerObject.initDraggable();
Also you can try setup Ext.util.ComponentDragger and Ext.resizer.Resizer for your existing component manually.
I am new to extjs.I want to associate a store on selecting a menu item from Ext.menu.Menu. I am using extjs 4.1.0. I searched on the net even went through sencha doc but I couldn't find any way to achieve this.
Is there some way to achieve it?
Thanks in advance.
I'm using a menu with a store in a project. Here's an example:
Ext.define("Ext.ux.menu.DynamicMenu", {
extend: "Ext.menu.Menu",
alias: 'widget.dynamicmenu',
loaded: false,
loadMsg: 'Loading...',
store: undefined,
icon: '',
constructor: function (config) {
var me = this;
Ext.apply(me, config);
me.callParent();
},
initComponent: function () {
var me = this;
me.callParent(arguments);
me.on('show', me.onMenuLoad, me);
listeners = {
scope: me,
load: me.onLoad,
beforeload: me.onBeforeLoad
};
me.mon(me.store, listeners);
},
onMenuLoad: function () { var me = this; if (!me.store.loaded) me.store.load(); },
onBeforeLoad: function (store) { this.updateMenuItems(false); },
onLoad: function (store, records) { this.updateMenuItems(true, records); },
updateMenuItems: function (loadedState, records) {
var me = this;
me.removeAll();
if (loadedState) {
me.setLoading(false, false);
Ext.Array.each(records, function (record, index, array) {
me.add({
text: record.get('DisplayName'),
data: record,
icon: me.icon
});
});
me.store.loaded = true;
}
else {
me.add({ width: 75, height: 40 });
me.setLoading(me.loadMsg, false);
}
me.loaded = loadedState;
}
});
I found this one on the sencha forums if IIRC, but can't find the link anymore. I made some tweaks for icons etc, ...
On the Ext.Array.each(records, ....
You'll need to define your own logic, It's depending on your model. My model has a DisplayName which I use to show as text. I also stock my record in a data property I made in the menu item. You're completely free there.
Good luck!
If I create a modal window:
Ext.define('myWindow', {
extend: 'Ext.Container',
alias: 'widget.myWindow',
floating: true,
modal: true,
listeners:
'onMaskClick???': { close the window }
.....
}
How do I know when a user has clicked on the mask outside the window? In Sench Touch, there is a config hideOnMaskTap that lets me specify. What is the event/config for extJS?
Tramway's case (sort of) works on modal or non modal windows. But not in case child components like the boundlist of a combobox float outside the windows boundaries.
However if you use modal windows anyway you can listen for a click event on the mask like this.
Ext.define('myWindow', {
extend: 'Ext.window.Window',
alias: 'widget.myWindow',
floating: true,
modal: true,
initComponent: function () {
var me = this;
me.callParent(arguments);
me.mon(Ext.getBody(), 'click', function(el, e){
me.close(me.closeAction);
}, me, { delegate: '.x-mask' });
}
});
You can listen all click events, then check if click position is out of the window
Ext.define('myWindow', {
extend: 'Ext.Container',
alias: 'widget.myWindow',
floating: true,
modal: true,
initComponent: function () {
this.initEvents();
this.callParent();
},
initEvents: function () {
//make sure your window is rendered and have sizes and position
if(!this.rendered) {
this.on('afterrender', this.initEvents, this, {single: true});
return;
}
this.mon(Ext.getBody(), 'click', this._checkCloseClick, this);
}
_checkCloseClick: function (event) {
var cx = event.getX(), cy = event.getY(),
box = this.getBox();
if (cx < box.x || cx > box.x + box.width || cy < box.y || cy > box.y + box.height) {
//clean up listener listener
this.mun(Ext.getBody(), 'click', this._checkCloseClick, this);
this.close();
}
}
}
You can try this also:
Ext.getBody().on('click', function(e, t){
var el = win.getEl();
if (!(el.dom === t || el.contains(t))) {
win.close();
}
});
I found adding a listener to the body and checking css classes felt a little hackey to me. You can actually override the private method _onMaskClick of Ext.ZIndexManager (see, completely not hackey). Which allows you to add your own configuration parameter (and even event) to all windows.
Ext.define('MyApp.ux.ZIndexManager_maskClick', {
override: 'Ext.ZIndexManager',
_onMaskClick: function ()
{
if (this.front)
{
var allowed = this.front.fireEvent('maskclick', this.front, this.mask);
if (allowed !== false && this.front.closeOnMaskClick)
this.front.close();
}
return this.callParent(arguments);
},
});