Migration from Sencha ExtJS 4.0 to ExtJS 4.1 - extjs

I create a window like this:
_target = new Ext.Window({
layer: 'top',
width: _width,
height: _height,
constrainTo: aBody,
constrain: true,
renderTo: aBody,
autoScroll: true,
flex: 1,
modal: (targetParams.Modal != undefined) ? targetParams.Modal : false,
resizable: (targetParams.Resizable != undefined) ? targetParams.Resizable : true,
minimizable: (targetParams.Minimizable != undefined) ? targetParams.Minimizable : true,
maximizable: (targetParams.Maximizable != undefined) ? targetParams.Maximizable : true,
closable: (targetParams.Closable != undefined) ? targetParams.Closable : true,
maximized: _maximized,
minimzed: _minimized,
isInFront: true
});
and then do this:
_target.on("render", function (items) {
if (items.length > 0) {
this.show();
this.add(items);
this.doLayout();
var buttonText = targetParams.ButtonText || this.title;
createToolbarButton(this.id, buttonText, targetParams.UIConfigurationId);
} else {
_target.destroy();
}
});
The problem is on this line this.show();. On 4.0 this line calls this function
show: function() {
this.callParent(arguments);
this.performDeferredLayouts();
return this;
},
But on the 4.1 the same line calls another function:
show: function(animateTarget, cb, scope) {
var me = this;
if (me.rendered && me.isVisible()) {
if (me.toFrontOnShow && me.floating) {
me.toFront();
}
} else if (me.fireEvent('beforeshow', me) !== false) {
me.hidden = false;
if (!me.rendered && (me.autoRender || me.floating)) {
me.doAutoRender();
}
if (me.rendered) {
me.beforeShow();
me.onShow.apply(me, arguments);
if (me.ownerCt && !me.floating && !(me.ownerCt.suspendLayout || me.ownerCt.layout.layoutBusy)) {
me.ownerCt.doLayout();
}
me.afterShow.apply(me, arguments);
}
}
return me;
},
In which down the line tries to do layout.renderChildren() and then it gives an error.
I think it's obvious that the objects created are different, but i haven't seen this question addressed in the "Upgrade 4.0 to 4.1" document.
So my question is what i have to do to make this work?
Thanks in advance for the help.
UPDATE:
The app structure after adding the window would look something like this:
ViewPort
North
...
West
...
Center
Window
Panel
Panel
Label
...
BorderSplitter
Panel
Label
...
Panel
List
South
...
I've made some changes to the code and it doesn't generated that error anymore.
_target.on("beforeRender", function (items) {
if (items.length > 0) {
_target.add(items);
_target.doLayout();
var buttonText = targetParams.ButtonText || _target.title;
createToolbarButton(_target.id, buttonText, targetParams.UIConfigurationId);
} else {
_target.destroy();
}
});
_target.show();
_target.toFront();
But now it generates another when I call _target.add(items);.
The error is "Unable to get the value of property 'dom'" on this line
me.container = container.dom ? container : Ext.get(container);
I've tried to analyze the call stack and found out why it give this error. When it calls this function:
renderChildren: function () {
var me = this,
items = me.getLayoutItems(),
target = me.getRenderTarget();
me.renderItems(items, target);
},
where "this" refers to the layout object of the window, to where I'm adding the items, the call "getRenderTarget()" returns undefined. Then tries to access the dom property of undefined, throwing the error I mentioned above.
This is where I'm lost because, as you can see, when I'm creating the window I pass an object (aBody) to the renderTo property.
Any ideas??

It had to do with the layout. With layout 'fit' it seems to work.

Related

ExtJS Drag and Drop in tree on modern toolkit

Actually I'm going to implement a tree view, where the user should have the option to reorder the structure with drag and drop. Actually I can't figure out how to enable drag and drop. I found a lot of examples using the 'treeviewdragdrop' plugin, which is just working with the classic toolkit.
The following Code made me move the first node but not more.
this.toParentSource = new Ext.drag.Source({
element: this.getView().element.down('.x-gridcell'),
constrain: {
element: this.getView().body,
vertical: true
}
});
Can you help me with this problem? I'm using ExtJS 6.5.2 modern toolkit.
This is how I enabled drag and drop for trees in modern Ext JS:
First I've written a plugin which creates the sources that should be draggable.
Plugin
Ext.define('test.component.plugin.TreeDragger', {
extend: 'Ext.AbstractPlugin',
alias: 'plugin.treedrag',
mixins: ['Ext.mixin.Observable'],
constructor: function (config) {
this.mixins.observable.constructor.call(this, config);
},
init: function (component) {
var me = this;
this.source = new Ext.drag.Source({
element: component.element,
handle: '.x-gridrow',
constrain: {
element: true,
vertical: true
},
describe: function (info) {
var row = Ext.Component.from(info.eventTarget, component);
info.row = row;
info.record = row.getRecord();
},
proxy: {
type: 'placeholder',
getElement: function (info) {
console.log('proxy: getElement');
var el = Ext.getBody().createChild({
style: 'padding: 10px; width: 100px; border: 1px solid gray; color: red;',
});
el.show().update(info.record.get('description'));
return el;
}
},
// autoDestroy: false,
listeners: {
scope: me,
beforedragstart: me.makeRelayer('beforedragstart'),
dragstart: me.makeRelayer('dragstart'),
dragmove: me.makeRelayer('dragmove'),
dragend: me.makeRelayer('dragend')
}
});
},
disable: function () {
this.source.disable();
},
enable: function () {
this.source.enable();
},
doDestroy: function () {
Ext.destroy(this.source);
this.callParent();
},
makeRelayer: function (name) {
var me = this;
return function (source, info) {
return me.fireEvent(name, me, info);
};
}
});
Next I used this plugin inside my tree.
Tree
xtype: 'tree',
hideHeaders: true,
plugins: {
treedrag: {
type: 'treedrag',
listeners: {
beforedragstart: function (plugin, info) {
// logic to identify the root and prevent it from being moved
console.log('listeners: beforedragstart');
}
}
}
},
columns: [{
xtype: 'treecolumn',
flex: 1,
}
]
Then I defined the drop targets inside the controller.
Controller
afterLoadApportionmentObjectsForTree: function (succes) {
if (succes) {
tree = this.getView().down('tree');
if (tree) {
tree.expandAll();
tree.updateHideHeaders(tree.getHideHeaders());
var store = tree.getStore();
store.remoteFilter = false;
store.filterer = 'bottomup';
this.createDropTargets();
}
}
},
createDropTargets: function () {
var me = this,
rows = tree.innerItems;
Ext.each(rows, function (el) {
var target = new Ext.drag.Target({
element: el.element,
listeners: {
scope: me,
drop: me.onDrop,
beforeDrop: me.onBeforeDrop
}
});
});
},
onDrop: function (target, info, eOpts) {
var source = info.record,
row = Ext.Component.from(target.getElement(), tree),
destination = row.getRecord(),
parentNode = source.parentNode;
destination.appendChild(source);
destination.expand();
if (!parentNode.hasChildNodes()) {
parentNode.set('leaf', true);
}
},
onBeforeDrop: function (target, info, eOpts) {
var source = info.record,
row = Ext.Component.from(target.getElement(), tree),
destination = row.getRecord();
// prevent the user to drop the node on itself
// this would lead to an error caused by recursive method calls
if (source == destination) {
return false;
}
// prevent the user to drop a node on it's children
// this would lead to an error caused by recursive method calls
if (source.findChild('number', destination.get('number'), true) != null) {
return false;
}
return true;
}

ExtJs 6 toolpip for combobox selected item

i have done toolpip for compobox list items
listConfig: {
itemTpl: [
'<div data-qtip="{description}">{mydisplayField}</div>'
]
now I'm trying to show tooltip for selected item,current value
i have search many times but I cant can't do to this .
If you have done task like this pleas tell me.
it was so easy
on afterrender
var fieldStore = field.getStore();
Ext.create('Ext.tip.ToolTip', {
target: field,
listeners: {
beforeshow: function updateTipBody(tip) {
var value = field.getValue();
if (!value && value !== 0) {
return false; //not show
}
var record = fieldStore.getById(value);
tip.update(record.get('description'));
}
}
});

Sencha Touch - How to dynamically change the row color of a grid?

I have a grid component with store in my view page.
{
xtype: 'grid',
store : { xclass : 'ABC.Store.MyStoreItem'},
}
I would like to change the row color depends on the value in the store.
Unfortunately, I only found the solution for ExtJS , but not for Sencha Touch.
In ExtJs, the row color can be change in this way: Styling row in ExtJS
viewConfig: {
stripeRows: false,
getRowClass: function(record) {
return record.get('age') < 18 ? 'child-row' : 'adult-row';
}
}
I want to have the exactly same thing in Sencha Touch, but I can't find the same method in the Sencha Touch API document, it only available in ExJs.
Does anyone have any other idea on how this feature can be done in Sencha Touch ?
Updated: Tried JChap' answer
I'm using sencha touch 2.3
According to JChap's answer. I had override the Grid class in this way.
The location of the file is
app > override > grid > Grid.js, with the code:
Ext.define('ABC.override.grid.Grid', {
override: 'Ext.grid.Grid',
updateListItem: function(item, index, info) {
var me = this,
record = info.store.getAt(index);
if (me.getItemClass) {
var handler = me.getItemClass(),
scope = me;
if (!handler) {
return;
}
if (typeof handler == 'string') {
handler = scope[handler];
}
cls = handler.apply(scope, [record, index, info.store]);
if(item.appliedCls) {
item.removeCls(item.appliedCls);
}
if (cls) {
item.addCls(cls);
item.appliedCls = cls;
}
}
this.callParent(arguments);
}
});
And my way of using it is different from JChap, below is my view page
Ext.define('ABC.view.Upload', {
extend: 'Ext.Container',
xtype: 'uploadList',
config: {
id: 'upload_view_id',
items: [
{
xtype: 'container',
layout: 'vbox',
height:'100%',
items:[
{
xtype: 'grid',
itemId : 'gridUpload',
store : { xclass : 'ABC.store.MyStoreItem'},
config: {
itemClass: function(record, index) {
var cls = null;
if(record.get('status') === 'new') {
cls = 'redRow';
}
else {
cls = 'greenRow';
}
return cls;
}
},
columns: [ ....]
}
]
}
]
}
});
I think I'm not using the override class corretly, can anyone point out my mistake ? Thanks.
There is no such option available in sencha touch. But we can add one by overriding List class. Here is how i overwritten the List class.
Ext.define('MyApp.overrides.dataview.List', {
override: 'Ext.dataview.List',
updateListItem: function(item, index, info) {
var me = this,
record = info.store.getAt(index);
if (me.getItemClass) {
var handler = me.getItemClass(),
scope = me;
if (!handler) {
return;
}
if (typeof handler == 'string') {
handler = scope[handler];
}
cls = handler.apply(scope, [record, index, info.store]);
if(item.appliedCls) {
item.removeCls(item.appliedCls);
}
if (cls) {
item.addCls(cls);
item.appliedCls = cls;
}
}
this.callParent(arguments);
}
});
And here is how to use it
Ext.define('MyApp.view.ProductList', {
extend: 'Ext.List',
xtype: 'productList',
config: {
itemClass: function(record, index) {
var cls = null;
if(record.get('status') === 'new') {
cls = 'x-item-new';
}
else if(record.get('status') === 'deleted') {
cls = 'x-item-dropped';
}
return cls;
}
}
});
Note: In my case i'm using List, since Grid extends from List this should work for you.

ExtJS - 'combocolumn' based renderer - rowediting does not register event or do what it is supposed to

http://2gears.com/2011/05/combobox-editor-remote-and-renderer-for-extjs-editorgridpanel/comment-page-2/#comment-11050?
Please see the function.
I am not using the 'combocolumn' completely. However i have used the major components. Please advise if there is a possibility it should work. As of now the grid refuses to render the column itself and I am unable to pinpoint what the bug is as the code is simply the same?
I did this not to act smart :) - but to simplify and run it on 1 column before standardizing the component common to the project.
The COMBO RENDERING fn()
<code>
function ComboBoxRenderer(combo, gridId) {
var getValue = function (value) {
var idx = combo.store.find(combo.valueField, value);
var rec = combo.store.getAt(idx);
if (rec) {
return rec.get(combo.displayField);
}
return value;
};
return function (value) {
if (combo.store.getCount() === 0 && gridId) {
console.log(combo.store.getCount()+gridId);
combo.store.on(
'load',
function () {
var grid = Ext.getCmp(gridId);
if (grid) {
grid.getView().refresh();
}
},
{
single: true
}
);
return value;
}
return getValue(value);
};
// Ext.getCmp(gridId).getView().refresh();
}
</code>
Editor - in Grid Column Model
{
header: 'Plan Type',
dataIndex: 'plan_id',
editor: {
// allowBlank: 'false',
xtype: 'combobox',
queryMode: 'local',
store: planTypeStore,
displayField: 'plan_name',
valueField: 'plan_id'
}
,renderer: ComboBoxRenderer(this.editor, 'gridPanelId')
/*this is the docs based renderrer - which wont work */
//, renderer: function (val) {
// var rec = planTypeStore.findRecord('plan_id', val);
// return (rec !== null ? rec.get("plan_name") : '');
// }

ExtJS4: this.ownerCt in initComponent function

Is there any way to access the parent component (via this.ownerCt) in the initComponent function?
While trying to access it via this.ownerCt, i found out that the ownerCt attribute is set after initComponent. So I do not know how i can hook in the initialization process of my component where i can change some parent's attributes.
I know this doesn't answer the question directly. I would have placed this in the comments to your question but I'm not allowed yet it would appear. If you are building breadcrumbs. I would look at extending the tab panel and creating a plugin for the Tab Bar that creates the kinda of navigation you want.
Ext.define('HOD.plugins.Breadcrumbs', {
// private
init : function(tabBar) {
tabBar.on('beforeadd', this.addIcons, this);
tabBar.on('beforeremove', this.handleTabRemove, this);
},
addIcons: function(tabBar, newTab, index, options) {
if (index > 0) {
newTab.iconCls = 'icon-arrow';
tabBar.items.each(function(tab) {
if (tab != newTab) {
tab.overCls = 'breadcrumbs-over'
}
});
}
},
handleTabRemove: function(tabBar, oldTab, options) {
var count = tabBar.items.getCount();
if (count > 1) {
var newTab = tabBar.items.getAt(count-2);
newTab.overCls = '';
newTab.removeCls('x-tab-breadcrumbs-over');
}
}
});
Then extend the tab panel so it uses the above plugin to style the tabs correctly.
Ext.define('HOD.view.GlobalNavigation', {
extend: 'Ext.tab.Panel',
border: false,
alias: 'widget.content',
requires: ['HOD.plugins.Breadcrumbs'],
tabBar: {
cls: 'breadcrumbs',
plugins: ['tabbarbreadcrumbs']
},
initComponent: function() {
this.on('tabchange', this.handleTabChange, this);
this.callParent(arguments);
},
push: function(tab) {
this.add(tab);
this.setActiveTab(tab);
},
pop: function() {
// Get the current cards;
var cards = this.getLayout().getLayoutItems();
if (cards.length > 1) {
this.setActiveTab(cards[cards.length-2]);
}
},
handleTabChange: function (tabPanel, newCard, oldCard, options) {
var cards = tabPanel.getLayout().getLayoutItems();
for (var i = (cards.length - 1); i > 0; i--) {
if (cards[i] !== newCard) {
this.remove(cards[i]);
} else {
break;
}
}
}
});
I've written up post about it here if you need more detail.
I would not recommend changing anything in the container from the inside element functions. Instead I would create an event in the element, fire that event and listen for it in the container.
This way your component will notify the container to do something, and container will do it itself.

Resources