ExtJS 4.2 resizable, draggable component - extjs

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.

Related

Unable to listen change event in controller

Am new in Ext JS community. Here I want to apply a change event to child component which is 'textfield'.
I have specified the 'onChangeSealNumber' function in the controller. But it's not getting fired.
Can someone help me into it?
I have tried many approaches, however, If I pass anonymous function on change, it will work. But it won't work when we explicitly specify as 'onChangeSealNumber'.
View File
/**
* Search Form Panel View.
* #class 'BulkTransaction.view.searchfrom.SearchForm'
*/
Ext.define('BulkTransaction.view.searchform.SearchForm', {
extend: 'Ext.container.Container',
requires: [
'Common.view.widget.RepeatingWidgetGroup',
'BulkTransaction.view.storagelocation.StorageLocation',
'BulkTransaction.view.searchform.SearchFormController',
],
alias: 'widget.searchform',
controller: 'searchformcontroller',
items: [
{
xtype: 'basepanel',
width: '100%',
reference: 'searchform',
header: false,
items: [
{
width: '100%',
xtype: 'connect-repeating-widget-group',
bind: {
store: '{topSealNumbers}'
},
bindReference: 'topSealNumbers',
widgetConfig: {
xtype: 'textfield',
fieldLabel: BulkTransaction.util.Constants.searchForm.topSealNumbers,
allowBlank: false,
bind: '{topSealNumbers.searchCriteria}',
cls: 'seal-number-field',
listeners: {
change: 'onChangeSealNumber'
}
}
}
]
}
]
});
Controler File
/**
* Controller containing the methods implementing functionality
* related to search form
*/
Ext.define('BulkTransaction.view.searchform.SearchFormController', {
extend: 'Ext.app.ViewController',
alias: 'controller.searchformcontroller',
init: function () {
const me = this;
const viewModel = me.getViewModel();
viewModel.bind({
bindTo: '{topSealNumbers}',
deep: true
}, me.onSearchCriteriaChange, me);
},
/**
* Handle change to the sealnumber details
* #private
*/
onSearchCriteriaChange: function (store) {
const me = this;
let searchCriteriaRecords;
searchCriteriaRecords = store.queryBy(rec =>{
if (!Ext.isEmpty(rec.get('searchCriteria').trim())) {
return rec;
}
});
this.fireEvent('toggleSearchButton', searchCriteriaRecords.length > 0);
},
onSealNumberChange (elm) {
const me = this,
view = me.getView();
}
});
In you controller you need to create a function named onChangeSealNumber something like this
Ext.define('BulkTransaction.view.searchform.SearchFormController', {
extend: 'Ext.app.ViewController',
alias: 'controller.searchformcontroller',
onChangeSealNumber: function(field, newValue, oldValue, eOpts) {
//do something here
},
})
You can try (MyApp - name of your application):
listeners: {change: MyApp.app.getController('SearchFormController').onChangeSealNumber()}
But as for me its not good way to work with controller. More better add into controller (inside init):
init: function (application) {
this.control({
"searchform textfield": {
change: this.onChangeSealNumber
},
});
}
As for identifier I'm not sure because as usually use itemId and name
(like `"#myItemId textfield[name=MyFieldName]"` )

extjs contextmenu click, pass parent grid as parameter to controller method

Inside my extjs grid, when I right click I call a context menu. When I click on one of the items I want to launch a method in the controller. This all works successfully, problem is I want to pass the parent grid that this is being called from into the controller method. Can someone please show me how to do this?
This is my context menu
Ext.define('Example.ContextMenuTradematch', {
xtype: 'contextMenuTradematch',
extend: 'Ext.menu.Menu',
items: [
{
text: 'Match Trade',
iconCls: 'greenIcon',
listeners: {
click: {
fn: 'onMatchTrade',
params: {
param1: this
}
}
}
},
{
text: 'Delete Trade',
iconCls: 'deleteIcon',
listeners: {
click: 'onDeleteTrade'
}
}
]
});
then this is my controller method
onMatchTrade: function (event, target, options) {
debugger;
var me = this;
How can I access the grid that the event originated from?
--and this is how I add the context menu to the grid
title: 'Tradematch Results: UNMATCHED',
xtype: 'grid',
itemId: 'gridUnmatchedId',
ui: 'featuredpanel-framed',
cls: 'custom-grid',
margin: '0px 10px 0px 10px',
flex: 2,
width: '100%',
bind: {
store: '{myTM_ResultsStore}'
},
listeners: {
itemcontextmenu: 'showContextMenuTradematch'
},
and this is how the controller adds it...
getContextMenu: function (cMenu) {
if (!this.contextMenu) {
debugger;
this.contextMenu = this.getView().add({ xtype: cMenu });
}
return this.contextMenu;
},
showContextMenuTradematch: function (view, rec, node, index, e) {
e.stopEvent();
e.stopEvent();
debugger;
this.getContextMenu('contextMenuTradematch1').show().setPagePosition(e.getXY());
return false;
},
The easiest way to do this is when you create your Example.ContextMenuTradematch instance - that I'm assuming you do from a itemcontextmenu listener - then you could pass a reference to the grid.
itemcontextmenu: function (grid, record, item) {
// code to create your menu
// probably something like:
if (!grid.contextMenu) {
grid.contextMenu = Ext.create('Example.ContextMenuTradematch', {
ownerGrid: grid
});
}
grid.contextMenu.showBy(item);
}
If onMatchTrade was fired by clicking on an Ext.menu.Item instance then it's signature will be:
onMatchTrade: function (item, e) {
var menu = item.up('menu'),
grid = menu.ownerGrid;
console.log(grid);
}
There was a lot of guessing here. If this is not how you are creating your menu or calling the methods, adding a fiddle with the issue would help.
Here is a fiddle to use as template: https://fiddle.sencha.com/#view/editor&fiddle/24fc

How to mask treepanel until loading success

I define a treepanel. And i try add mask() for waiting tree is loading done. But not working.
Here is my code
Ext.define('Example.example', {
extend: 'Ext.tree.Panel',
alias: 'widget.example',
title: 'example',
store: Ext.create('Ext.data.TreeStore', {
...
listeners: {
'load': function (store, records, success) {
Ext.ComponentQuery.query('example').getEl().unmask(); // not working
},
'beforeload': function (store, options) {
Ext.ComponentQuery.query('example').getEl().mask();// not working
}
}
})
});
How to make that working thank.
EIther use the undocumented ownerTree property:
beforeload: function() {
this.ownerTree.getEl().mask("Loading", 'x-mask-loading');
}
Or register your listeners in a method in order to get the scope:
Ext.define('Example.example', {
// ...
,initComponent: function() {
this.callParent(arguments);
this.getStore().on({
scope: this
,beforeload: function() {
this.getEl().mask("Loading", 'x-mask-loading');
}
});
}
});
try this one Ext.ComponentQuery.query('example').body.mask(); use body instead of getEl()

Asscociating a store with Ext.menu.Menu

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!

How to close modal window extjs when clicking on mask?

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);
},
});

Resources