Customizing shared component - extjs

Ext.define('RevenuePanel', { extend: 'Ext.panel.Panel',
items: [
..........
Ext.create('Ext.button.Button', {text: 'Button'}) ]
});
In this case,I believe the items property is copied to the class's prototype.
What is the good programming practice/s to allow the panel to have custom behaviour for its items at multiple containers which would use it within the application?
We are on Ext3.4x

I assume that you just want to add more items, without overriding the predefined.
Ext.define('RevenuePanel', {
extend: 'Ext.panel.Panel',
initComponent: function(){
var me = this,
newItems = me.items,
defaultItems, items;
// apply your default items
defaultItems = [{xtype:'button', text:'Button'}];
// check if there are new items defined for this instance
if(typeof newItems != 'undefined') {
items = defaultItems.concat((newItems instanceof Array ) ? newItems : [newItems]);
} else {
items = defaultItems;
}
// override the items
me.items = items;
me.callParent(arguments);
}
});

Related

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.

Drag and Drop from Grid to Tree and backwards

Since a few days now I try to change an ExtJs ['Grid to Tree Drag and Drop' Example][1] to work in both directions. But all I get is an 'almost' working application.
Now it works as far as I can drag an item from grid to tree, within tree, within grid but if i drag it from tree to grid, it doesn't drop. It just shows the green hook.
I also tried to differ the ddGroup from tree and grid, but then nothing works anymore.
This is too much for an ExtJs beginner.
// Stücklisten Grid
stuecklistengrid = Ext.extend(Ext.grid.GridPanel, {
initComponent:function() {
var config = {
store:itemPartStore
,columns:[{
id:'PART_ITE_ID'
,header:"PART_ITE_ID"
,width:200, sortable:true
,dataIndex:'PART_ITE_ID'
},{
header:"IS_EDITABLE"
,width:100
,sortable:true
,dataIndex:'IS_EDITABLE'
},{
header:"IS_VISIBLE"
,width:100
,sortable:true
,dataIndex:'IS_VISIBLE'
}]
,viewConfig:{forceFit:true}
}; // eo config object
// apply config
Ext.apply(this, Ext.apply(this.initialConfig, config));
this.bbar = new Ext.PagingToolbar({
store:this.store
,displayInfo:true
,pageSize:10
});
// call parent
stuecklistengrid.superclass.initComponent.apply(this, arguments);
} // eo function initComponent
,onRender:function() {
// call parent
stuecklistengrid.superclass.onRender.apply(this, arguments);
// load the store
this.store.load({params:{start:0, limit:10}});
} // eo function onRender
});
Ext.reg('examplegrid', stuecklistengrid);
// Stücklisten Tree
var CheckTree = new Ext.tree.TreePanel({
root:{ text:'root', id:'root', expanded:true, children:[{
text:'Folder 1'
,qtip:'Rows dropped here will be appended to the folder'
,children:[{
text:'Subleaf 1'
,qtip:'Subleaf 1 Quick Tip'
,leaf:true
}]
},{
text:'Folder 2'
,qtip:'Rows dropped here will be appended to the folder'
,children:[{
text:'Subleaf 2'
,qtip:'Subleaf 2 Quick Tip'
,leaf:true
}]
},{
text:'Leaf 1'
,qtip:'Leaf 1 Quick Tip'
,leaf:true
}]},
loader:new Ext.tree.TreeLoader({preloadChildren:true}),
enableDD:true,
ddGroup:'grid2tree',
id:'tree',
region:'east',
title:'Tree',
layout:'fit',
width:300,
split:true,
collapsible:true,
autoScroll:true,
listeners:{
// create nodes based on data from grid
beforenodedrop:{fn:function(e) {
// e.data.selections is the array of selected records
if(Ext.isArray(e.data.selections)) {
// reset cancel flag
e.cancel = false;
// setup dropNode (it can be array of nodes)
e.dropNode = [];
var r;
for(var i = 0; i < e.data.selections.length; i++) {
// get record from selectons
r = e.data.selections[i];
// create node from record data
e.dropNode.push(this.loader.createNode({
text:r.get('PART_ITE_ID')
,leaf:true
,IS_EDITABLE:r.get('IS_EDITABLE')
,IS_VISIBLE:r.get('IS_VISIBLE')
}));
}
// we want Ext to complete the drop, thus return true
return true;
}
// if we get here the drop is automatically cancelled by Ext
}}
}
});
// Stücklisten Container
var itemPartList = new Ext.Container({
id: 'itemPartList',
title: 'Stücklisten',
border:false,
layout:'border',
items:[CheckTree, {
xtype:'examplegrid'
,id:'SLgrid'
,title:'Grid'
,region:'center'
,layout:'fit'
,enableDragDrop:true
,ddGroup:'grid2tree'
,listeners: {
afterrender: {
fn: function() {
// This will make sure we only drop to the view scroller element
SLGridDropTargetEl2 = Ext.getCmp('SLgrid').getView().scroller.dom;
SLGridDropTarget2 = new Ext.dd.DropTarget(SLGridDropTargetEl2, {
ddGroup : 'grid2tree',
notifyDrop : function(ddSource, e, data){
var records = ddSource.dragData.selections;
Ext.each(records, ddSource.grid.store.remove,
ddSource.grid.store);
Ext.getCmp('SLgrid').store.add(records);
return true
}
});
}
}
}
}]
});
You need to implement the onNodeDrop event of the grid. See http://docs.sencha.com/ext-js/4-1/#!/api/Ext.grid.header.DropZone-method-onNodeDrop

Sencha Touch 2 - Populate a TitleBar using a store

I am working with Sencha Touch 2 and I need to create a TitleBar which is sucked into a set of screens. The TitleBar elements are drop-down lists. The items within the drop-down lists must be dynamic and must be loaded from a data file.
I've managed to load the data but I cannot pass the data back to the TitleBar. In other words, I need somehow to create a reference to the titlebar.
Code:
Ext.define('CustomerToolbar', {
extend: 'Ext.TitleBar',
xtype: 'customer-toolbar',
initialize: function() {
this.callParent(arguments);
this.loadItems();
console.info("end of init");
},
config: {
layout: 'hbox',
defaults: {
}
},
loadItems: function (titleBar) {
var itemList = [];
var itemOptionList = [];
Ext.getStore('OrganizationStore').load(function(organizationList) {
console.info("getOptionList inside the store load function");
Ext.each(organizationList, function(organization) {
console.info("organizations: " + organization.get("name") + "," + organization.get("id"));
itemOptionList.push({text: organization.get("name"), value: organization.get("id")});
});
console.info("itemList - about to populate");
itemList.push(
{
xtype: 'selectfield',
name: 'customerOptions',
id :'organizationId',
options: itemOptionList,
action :'selectOrganizationAction'
}
);
console.info("itemList - populated");
console.info("itemList within the store block: " + itemList);
console.info("this: " + this);
//THIS IS WHERE I AM HAVING THE PROBLEM.
//The variable this points to the store and not to the TitleBar
//this.setItems(itemList);
});
console.info("itemList outside the store block: " + itemList);
}
});
You can add a listener to your selectfield and do
listeners:{
change:function(){
title = Ext.getCmp('organizationId').getValue();
Ext.getCmp('TitlBarID').setTitle(title);
}
}
I know Ext.getCmp is not fashionable but it works

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.

ExtJS 4 > Row Editor Grid > How to Change "Update" Button Text

Is there any way to change the text of "Update" button in ExtJS-4 Row Editor Grid ?
Good question, I had a look through the source code and whilst there is nothing inside the RowEditing plugin, in the class it extends 'RowEditor.js' there is the following:
Ext.define('Ext.grid.RowEditor', {
extend: 'Ext.form.Panel',
requires: [
'Ext.tip.ToolTip',
'Ext.util.HashMap',
'Ext.util.KeyNav'
],
saveBtnText : 'Update',
cancelBtnText: 'Cancel',
...
});
So I'd assume you'd just need to override the 'saveBtnText' in your instance of 'Ext.grid.plugin.RowEditing' as it calls the parent constructor with callParent(arguments) in the RowEditing class
Not that easy and not without hacking in undocumented areas. The problem is, that the Ext.grid.plugin.RowEditing directly instantiates the Ext.grid.RowEditor without allowing you to pass in configuration options. So in general you have to override the initEditor() method in the plugin and instantiate your own row editor:
// ...
plugins: [{
ptype: 'rowediting',
clicksToEdit: 2,
initEditor: function() {
var me = this,
grid = me.grid,
view = me.view,
headerCt = grid.headerCt;
return Ext.create('Ext.grid.RowEditor', {
autoCancel: me.autoCancel,
errorSummary: me.errorSummary,
fields: headerCt.getGridColumns(),
hidden: true,
// keep a reference..
editingPlugin: me,
renderTo: view.el,
saveBtnText: 'This is my save button text', // <<---
cancelBtnText: 'This is my cancel button text' // <<---
});
},
}],
// ...
For ExtJS 4
Ext.grid.RowEditor.prototype.cancelBtnText = "This is cancel";
Ext.grid.RowEditor.prototype.saveBtnText = "This is update";
This solution is to define the prototype of rowEditors. that means that this config is than general.
If you want to change it just for one editor, or if you want to get different configs , the prototype is definitely not the solution.
look at source code :
initEditorConfig: function(){
var me = this,
grid = me.grid,
view = me.view,
headerCt = grid.headerCt,
btns = ['saveBtnText', 'cancelBtnText', 'errorsText', 'dirtyText'],
b,
bLen = btns.length,
cfg = {
autoCancel: me.autoCancel,
errorSummary: me.errorSummary,
fields: headerCt.getGridColumns(),
hidden: true,
view: view,
// keep a reference..
editingPlugin: me
},
item;
for (b = 0; b < bLen; b++) {
item = btns[b];
if (Ext.isDefined(me[item])) {
cfg[item] = me[item];
}
}
return cfg;
}`
this method inits the rowEditor, and there's a loop on btns Array:
btns Array :
btns = ['saveBtnText', 'cancelBtnText', 'errorsText', 'dirtyText']
for (b = 0; b < bLen; b++) {
item = btns[b];
if (Ext.isDefined(me[item])) {
cfg[item] = me[item];
}
}
In this loop foreach string in btnArray it's searched if exists in cfg the same string property, if it's found it's added to config. You just have to manage that this loop finds what you want to modify:
Example: we want to change the text of save button:
the property saveBtnText which is the first item of btns Array must exists in cfg:
if (Ext.isDefined(me[item])) {
cfg[item] = me[item];
}
this search if property exists : if (Ext.isDefined(me[item]))
if saveBtnText already exists in rowEditor properties then:
cfg[item] = me[item];
and the additional config property will be set!!

Resources