Extjs conditional configuration of initComponent - extjs

I'm quite new to Extjs and I can't figure this out:
I have a Container that requires a panel. Is there a way to dynamically initialise a component? This is my view:
Ext.define('Hello.view.index.Resume', {
extend: 'Ext.container.Container',
requires: [
'Hello.view.index.ValuesChart',
],
initComponent: function() {
this.leftZone = [{
margin: '0 0 5 0',
ui: 'hello-toggable',
xtype: 'hello_index_characteristics'
}];
Ext.apply(this, {
items: [{
xtype: 'container',
items: [{
xtype: 'hello_index_valueschart',
}, {
// ....
}]
}]
});
this.callParent();
}
});
The hello_index_valueschart panel has an initComponent function that defines several items:
initComponent: function() {
Ext.apply(this, {
border:false,
dockedItems: [{
xtype: 'toolbar',
dock: 'bottom',
items: [
{
xtype: 'tbspacer',
width: 15
},
'->',
{
xtype:'button',
customproperty: this.id,
text:'I am a text',
tooltip: 'Hi there'
},
{
xtype:'button',
customproperty: this.id,
text:'I am another text',
tooltip: 'Hi here'
}
]
}]
})
}
Is there a way to dynamically pass the items to this panel? I mean for example: if a condition is verified in the controller pass an array items1 otherwise pass array items2.

A quick thought:
you can use the afterrender event on the panel, then add the components based on a condition in the controller. Something like:
Ext.define('MyApp.controller.MyController', {
extend: 'Ext.app.Controller',
onPanelAfterRender: function(component, eOpts) {
if(this.someCondition()) {
component.add( { ... });
}
},
someCondition: function() {
return true;
}
init: function(application) {
this.control({
"#mypanel": {
afterrender: this.onPanelAfterRender
}
});
}
});

Related

Sencha touch DataView cannot scroll vertically properly

i am using a customized DataView in my app, this DataView was set to scroll vertically and been added into a panel later.
But now the DataView cannot scroll properly, the problem is:
when i drop down the DataView, it can scroll down, but when i release my finger, it scroll back to top automatically.
could anybody help to check what's the reason?
thanks~~
here is my codes:
==============The DataView==============
Ext.define("cherry.view.UserActivityList", {
extend: 'Ext.dataview.DataView',
xtype: 'user-activity-list',
requires: [
'cherry.store.UserActivityStore',
'Ext.dataview.DataView',
'Ext.XTemplate'
],
config: {
styleHtmlContent: true,
height: '100%',
itemTpl: new Ext.XTemplate(
'<tpl for=".">',
'<div class="activity-ctn">',
' <div class="activity-content">{content}</div>',
'</tpl>'
)
},
initialize: function () {
this.callParent(arguments);
var me = this;
var store = Ext.getStore('user-activity-store');
store.load();
me.setStore(store);
}
});
============Panel contains the DataView============
Ext.define('cherry.view.Main', {
extend: 'Ext.Panel',
xtype: 'main',
requires: [
'cherry.view.ComposeToolbar',
'cherry.view.Menubar',
'cherry.view.UserActivityList'
],
config: {
layout: 'card',
id: 'main-container-view',
scrollable: null,
items: [
{
docked: 'top',
xtype: 'toolbar',
title: 'cherry',
id: 'main-toolbar',
cls: 'main-toolbar',
items: [
{
xtype: 'button',
iconCls: 'menu2',
text: 'Menu',
iconMask: true,
handler: function () {
Ext.Viewport.toggleMenu('left');
}
},
{
xtype: 'spacer'
},
{
xtype: 'button',
iconCls: 'loop2',
text: 'Refresh',
iconMask: false,
handler: function () {
Ext.getStore('user-activity-store').load();
Ext.ComponentQuery.query('#user-activities-list-view')[0].refresh();
}
}
]
},
{
xtype: 'compose-toolbar'
},
{
xtype: 'user-activity-list',
id: 'user-activities-list-view',
itemId: 'user-activities-list-view',
layout: 'fit',
height:'100%',
cls:'dataview-ctn',
scrollable:{
direction:'vertical'
}
}
]
},
initialize: function () {
Ext.Viewport.setMenu(cherry.view.Menubar.createMenu('left'), {
side: 'left',
reveal: true
});
}
});
It seems that your error is due to the layout config in user-activity-list
{
xtype: 'user-activity-list',
id: 'user-activities-list-view',
itemId: 'user-activities-list-view',
layout: 'fit',
height:'100%',
cls:'dataview-ctn',
scrollable:{
direction:'vertical'
}
}
A dataview must ALWAYS! have its layout to Auto. As stated by the constructor, which by the way you should be seeing a log error.
constructor: function(config) {
var me = this,
layout;
me.hasLoadedStore = false;
me.mixins.selectable.constructor.apply(me, arguments);
me.indexOffset = 0;
me.callParent(arguments);
//<debug>
layout = this.getLayout();
if (layout && !layout.isAuto) {
Ext.Logger.error('The base layout for a DataView must always be an Auto Layout');
}
//</debug>
}
Try removing the layout config it should fix your error.
Cheers!

Sencha Touch 2.3: Pushing data from list view to detail view

So I have made a simple list component view. When I tap a listing's disclosure button, I have a controller that will create a detail view that also pushes data about that respective listing into the detail view for use in a tpl property.
here is my code:
app/view/Main:
Ext.define ('Prac.view.Main', {
extend: 'Ext.Panel',
xtype: 'mainpanel',
requires: ['Prac.store.Names'],
config:{
layout: 'vbox',
items: [
{
xtype: 'titlebar',
docked: 'top',
title: 'Mainpanel',
items: [
{
xtype: 'button',
ui: 'confirm',
iconCls: 'add',
action: 'addName',
align: 'right'
}
]
},
{
xtype: 'list',
flex: 1,
grouped: true,
indexBar: true,
itemTpl: '{firstName} {lastName}',
store: 'Names',
onItemDisclosure: true,
}
]
}
});
app/controller/Main:
Ext.define ('Prac.controller.Main', {
extend: 'Ext.app.Controller',
config: {
refs: {
view: 'viewpanel',
det: 'detail'
},
control: {
'list' : {
disclose: 'showDetail'
}
}
},
showDetail: function(list, record) {
var det = Ext.create('Prac.view.Detail', {
data: record.data
});
Ext.Viewport.setActiveItem(det);
}
});
app/view/Detail:
Ext.define('Prac.view.Detail', {
extend: 'Ext.Panel',
xtype: 'detail',
config: {
items: [
{
xtype: 'titlebar',
title: 'Detail View',
docked: 'top'
},
{
xtype: 'panel',
styleHtmlContent: true,
scrollable: 'vertical',
title: 'Details',
//html: 'Hello, World!'
tpl: 'Hello {firstName} {lastName}',
data: null
}
]
}
});
I think that the issue might be of scope. Since the tpl property is nested inside the 'items' property rather than the config, the component is unable to use the data passed to the detail view from the controller. So I am wondering not just how to push data from one view to another, but how to push data from one view to a specific component in another view.
You are absolutely right. You are not setting data of the nested panel, you are setting the data of the Prac.view.Detail instead.
Data is a config property of a panel. That means sencha will create a setData() method for you. When you use this method internally applyData() or updateData() will be called respectively.
In your case this should work:
Ext.define('Prac.view.Detail', {
extend: 'Ext.Panel',
xtype: 'detail',
config: {
items: [
{
xtype: 'titlebar',
title: 'Detail View',
docked: 'top'
},
{
xtype: 'panel',
styleHtmlContent: true,
scrollable: 'vertical',
title: 'Details',
//html: 'Hello, World!'
tpl: 'Hello {firstName} {lastName}',
data: null
}
]
},
updateData: function ( newData, oldData ) {
var nestedPanel = this.down( 'panel' );
nestedPanel.setData( newData );
},
applyData: function ( newData, oldData ) {
var nestedPanel = this.down( 'panel' );
nestedPanel.setData( newData );
}
});
So when one sets the data of the Prac.view.Detail the applyData method will be called and it grabs the nested panel to set its data instead.

dockedItems - text from Panel

I have Tree panel.
everything works!;
Ext.define('My.Tree', {
extend:'Ext.tree.Panel',
id: 'DriveTree',
store: storeTree,
ChooseButtonText: 'ChooseFolder',
dockedItems: [{
xtype: 'toolbar',
items: [{
text: 'BUTTON TEXT', // this.ChooseButtonText
id:'connectButton',
handler: function(){
alert(this.ChooseButtonText);
}
},
]
}],
});
Ext.onReady(function(){
var tree =Ext.create('My.Tree', {});
});
But text of dockedItems want to be from Panel. something like this:
text:this.ChooseButtonText
each dockedItems have listener - handler: function(){}. How can I see that variables in this function too?
Do it in initComponent:
Ext.define('My.Tree', {
extend: 'Ext.tree.Panel',
id: 'DriveTree',
store: storeTree,
ChooseButtonText: 'ChooseFolder',
initComponent: function() {
this.dockedItems = [{
xtype: 'toolbar',
items: [{
text: this.ChooseButtonText,
scope: this,
handler: this.onConnectButtonClick
}]
}];
this.callParent();
},
onConnectButtonClick: function() {
console.log('Do something');
}
});

Adding buttons to a view from its controller in ExtJS 4.1

I've the following code:
// wlpt.js
Ext.onReady(function() {
Ext.application({
name: 'WLPT',
appFolder: 'app',
controllers: ['MenuPanel'/*, 'Employees'*/],
launch: function() {
WLPT.application = this;
},
autoCreateViewport: true
});
});
//viewport.js
Ext.define('WLPT.view.Viewport', {
extend:'Ext.container.Viewport',
id:'viewport',
requires:[
'WLPT.view.Header',
'WLPT.view.MenuPanel'
],
layout: 'fit',
initComponent: function() {
this.items = {
layout: 'border',
items: [{
region: 'north',
xtype: 'headerview',
height: 80
},{
region: 'west',
id: 'westernPanel',
xtype: 'menupanelview',
width: 200,
collapsible: true
},{
xtype: 'panel',
title: 'Center Panel',
region: 'center'
}]
};
this.callParent();
}
});
// controller/MenuPanel.js
Ext.define('WLPT.controller.MenuPanel', {
extend: 'Ext.app.Controller',
currentYear: 0,
views:['MenuPanel'],
refs:
[{
selector: '.menupanel',
ref: 'menuPanel'
},{
selector: '#centerPanel',
ref: 'centerPanel'
}],
init: function() {
var d = new Date();
this.currentYear = d.getFullYear();
this.control({
'#btnEmployee': {
click: this.btnEmployeeClicked
}
});
this.callParent(arguments);
rolevalue = 10;
if (rolevalue == 10) {
// user is member of administration group
this.addAdminButtons();
}
},
addAdminButtons:function() {
console.log('addAdminButtons');
**this.getMenuPanelView().add({
xtype:'button',
scale: 'large',
text: 'Projects',
itemId: 'btnProject'
});**
}
});
// view/MenuPanel.js
Ext.define('WLPT.view.MenuPanel', {
extend: 'Ext.panel.Panel',
alias: 'widget.menupanelview',
bodyPadding: 2,
title: 'Menu Panel',
layout: {
type:'vbox',
align:'stretch'
},
items: [{
xtype:'label',
height: 10
}],
autoShow: true,
initComponent: function() {
this.callParent(arguments);
}
});
My problem is that the controller doesn't add the button on the view. I get the followig error:
Uncaught TypeError: Object function h(){return
this.constructor.apply(this,arguments)||null} has no method 'add'
What am I doing wrong?
Thanks for your help in advance
You need to add a reference to your menupanel. assign your menupanel an itemId: menupanel and in your controller you can reference it can reference it with: #menupanel. I noticed that you have .menupanel as the selector which I'm not sure is completely correct.
I also noticed that your are doing this.getMenuPanelView() which not correct as you don't have a reference to menuPanelView in your controller.
TIP:
Also you could use your browser's debugging tool(Google Chrome is my favorite) and add break points in your code to easily evaluate your code.

show window in tabpanel

I am working on extjs4, my case is:
Extjs mvc is used to build my application, viewport is the toppest container of my application, west region is a tree, center region is a tabpage container, when click the tree item, a new page with certain content will be created. then in this page, I popup a model window, this model window just mask the page, not the whole viewport, so that I can still click the tree item to open another new page.
I have achieved this, but there is a problem, if I have already open a model window in a tab, and I switch to a another tab then return back, the model window is hidden, but I still want that window to show if I haven't closed it. Can anyone help me, is there a better way except using ifram in tabpage?
app.js:
Ext.application({
name: 'SysOpv',
appFolder: '/Js/AppSysOpv/app',
autoCreateViewport: true,
controllers: [
'Category',
'Band'
]
});
Viewport:
Ext.define('SysOpv.view.Viewport', {
extend: 'Ext.container.Viewport',
layout: 'fit',
initComponent: function() {
this.items = {
dockedItems: [{
dock: 'top',
xtype: 'toolbar',
height: 80,
items: [
{ xtype: 'component', html: 'setup' }
]
}],
layout: {
type: 'hbox',
align: 'stretch'
},
items: [{
width: 250,
xtype: 'categorytree'
}, {
id: 'maintabpanel',
flex: 1,
xtype: 'tabpanel'
}]
};
this.callParent(arguments);
}
});
Tree View:
Ext.define('SysOpv.view.category.Tree', {
extend: 'Ext.tree.Panel',
alias: 'widget.categorytree',
title: 'setup',
rootVisible: false,
useArrows: true,
hideHeaders: true,
columns: [{
flex: 1,
xtype: 'treecolumn',
text: 'Name',
dataIndex: 'name'
}],
store: 'Category',
initComponent: function() {
this.callParent(arguments);
}
});
Window View:
Ext.define('SysOpv.view.edit.Band', {
extend: 'Ext.window.Window',
alias: 'widget.editband',
title: 'Setup',
layout: 'fit',
constrain: true,
modal: true,
initComponent: function() {
this.items = [{
xtype: 'form',
bodyPadding: 10,
items: [{
xtype: 'textfield',
name: 'name',
fieldLabel: 'Name'
}]
}];
this.buttons = [{
text: 'Save',
action: 'save'
}, {
text: 'Cancel',
scope: this,
handler: this.close
}];
this.callParent(arguments);
}
});
Tree Controller:
Ext.define('SysOpv.controller.Category', {
extend: 'Ext.app.Controller',
models: [ 'Category' ],
stores: [ 'Category' ],
views: [ 'category.Tree' ],
init: function() {
this.control({
'categorytree': {
itemdblclick: this.onTreeItemdblclick
}
});
},
onTreeItemdblclick: function (tree, record, item, index, e, eOpts) {
var mainTabs = Ext.getCmp('maintabpanel');
var tabId = record.get('id');
if (mainTabs) {
var checkTab = mainTabs.getComponent(tabId);
if (checkTab) {
mainTabs.setActiveTab(checkTab);
} else {
var controller;
var list;
switch (tabId) {
case '0101':
list = Ext.widget('listband');
break;
}
if (list)
{
var tabPage = mainTabs.add({
id: record.get('id'),
title: record.get('name'),
closable: true,
layout: 'fit',
items: [ list ]
});
mainTabs.setActiveTab(tabPage);
}
}
}
}
});
Module Controller:
Ext.define('SysOpv.controller.Band', {
extend: 'Ext.app.Controller',
models: [ 'Band' ],
stores: [ 'Band' ],
views: [ 'list.Band', 'edit.Band' ],
init: function() {
this.control({
'listband button[action=edit]': {
click: this.onEdit
}
});
},
onEdit: function(button, e, eOpts) {
var edit = Ext.widget('editband');
var list = button.up('gridpanel');
if (list.getSelectionModel().hasSelection()) {
var record = list.getSelectionModel().getLastSelected();
// I use renderTo here but have no effect,
// so I search in the google find a way to show the window in tab,
// and not mask all the viewport.
button.up('#0101').add(edit);
edit.down('form').loadRecord(record);
edit.show();
} else {
console.log('Not selected');
}
}
});
Below is example solution:
Ext.create('Ext.TabPanel', {
renderTo: 'container',
items: [
{
title: 'Tab 1',
itemId: 'tab1',
items: [
{ xtype: 'button', text: 'Show window', handler: function(){
var tab = this.up('#tab1'); // Find tab
var win = Ext.widget('editband'); // Find window
this.up('tabpanel').showWindow(tab, win);
} }
]
},
],
showWindow: function(tab, w){
tab.add(w);
tab.popup = w;
w.on('close', function() { // clean up after window close
delete this.popup;
}, tab, { single: true });
w.show();
},
listeners: {
tabchange: function(panel, tab) {
if (tab.popup !== undefined) { // show window after tab change
tab.popup.show();
}
}
}
});
Basically I've created event handler for tabchange event in which I re-show window.
Working sample: http://jsfiddle.net/aCxYU/1/

Resources