How can I split the logic for an HPC Gateway Addon into separate files? i.e. I'd like to do something like this:
Main.js
Ext.define('App.view.main.Main', {
extend: 'Ext.tab.Panel',
items: [{
title: 'Stuff',
xtype: 'stuff',
iconCls: 'x-fa fa-object-group'
}, {
title: 'About',
xtype: 'about',
iconCls: 'x-fa fa-info-circle',
}]
});
Stuff.js
Ext.define('App.widget.Stuff', {
extend: 'Ext.panel.Panel',
alias: 'widget.stuff',
html: '<h1>Stuff'
});
About.js
Ext.define('App.widget.About', {
extend: 'Ext.panel.Panel',
alias: 'widget.about',
html: '<h1>Version: x.y.z'
});
According to the official fujitsu docs for creating an addon, there are no examples of separating your logic into multiple files, just two monolithic files which contain the view & the controller logic:
appModule.js
Ext.define('desktop.addons.app_abcdef12.view.appModule', {
extend: 'desktop.core.utils.Module',
requires:[],
/**
* Create window
* #param taskBar the task bar
* #returns {desktop.core.view.utils.ModuleView} the module view
*/
createWindow: function (taskBar) {
var me = this;
return Ext.create('desktop.core.view.utils.ModuleView', {
title: me.title,
iconCls: me.iconCls,
stateId: 'app-module',
name: 'app-window',
taskBar: taskBar,
multipleView: false,
width: 320,
height: 150,
items:me.buildItems(),
buttons: [
]
});
},
/**
* Build items
* #returns {{xtype: string, layout: {type: string, align: string}, items: *[]}} items in json format
*/
buildItems:function(){
return {
xtype: 'panel',
layout: 'center',
items: [{
xtype: 'textfield',
name: 'value',
fieldLabel: desktop.core.utils.Symbols.getText('app_abcdef12.textfield.input')+" *",
allowBlank:false,
listeners: {
change: function(textfield, newValue){
var window = textfield.up('window');
window.fireEvent('textfieldChanged', textfield, newValue);
}
}
}]
};
}
});
appController.js
Ext.define('desktop.addons.app_abcdef12.controller.appController', {
extend: 'desktop.core.controller.abstract.AbstractToriiController',
requires: [],
control: {
'window[name=app-window]': {
textfieldChanged: 'performTextfieldChanged'
}
},
performTextfieldChanged: function (textfield, newValue) {
if (Ext.isEmpty(newValue)) {
textfield.up('window').down('button[name=save]').disable();
} else {
textfield.up('window').down('button[name=save]').enable();
}
}
});
When I tried to create something like desktop.addons.app_abcdef12.view.Stuff with an xtype of widget.stuff I crashed the HPC instance, and had to delete the addon listed in mongodb and restart the services. This seriously reduces the number of times I can use trial and error to find out what works.
Anybody done this before?
In the end I didn't manage to get anything working using xtype but I did when using Ext.create directly:
appModule.js
buildItems:function(){
return {
xtype: 'tabpanel',
items: [
Ext.create('desktop.addons.app_abcdef12.view.Stuff'),
Ext.create('desktop.addons.app_abcdef12.view.About'),
]
};
}
Stuff.js
Ext.define('desktop.addons.app_abcdef12.view.Stuff', {
title: 'Stuff',
extend: 'Ext.panel.Panel',
iconCls: 'x-fa fa-id-card',
html: '<h1>Stuff'
});
About.js
Ext.define('desktop.addons.app_abcdef12.view.About', {
title: 'About',
extend: 'Ext.panel.Panel',
iconCls: 'x-fa fa-info',
html: '<h1>About'
});
Related
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.
I am new to Senscha Touch and I have been struggling with this for hours.
I am trying to create an application where the main page has 1-3 tabs where title and content(html5) depends on json data.
My model has two fields: "title" and "text".
My store has dummy data for 2 tabs:
Ext.define('***', {
extend: 'Ext.data.Store',
config: {
model: '***',
xtype: 'informationTabs',
data: [
{
title: 'Museum',
text: 'Random html5'
},
{
title: 'Museum_2',
text: 'Random html5_2'
},
{
title: 'Museum_3',
text: 'Random html5_2'
}
]
}
})
To show it as a list i have the following code:
Ext.define('***', {
extend: 'Ext.Panel',
xtype: 'informationsTabs',
config: {
title: 'InformationTabs',
layout: 'fit',
items: [
{
xtype: 'list',
store: 'InformationTabs',
itemTpl: '{title}, {text}'
}
]
}
});
How do I get that to instead of making a list with two items, create two tabs with their title and text inside?
So in this case i should have two tabs.
Tab 1: Title = "title_1", content = "random_html5"
Tab 2: Title = "title_2", content = "random_html5_2"
Update:
With the following code (thanks kevhender!) it "works", except i get an extra "[object Object]" as the first tab. This option is also the only one with blue background when you click that tab.
Also this.callParent(); gets "Unresolved function or method".
Ext.define('***', {
extend: 'Ext.TabPanel',
xtype: 'informationsTabs',
config: {
title: 'informationsTabs',
items: [
{
xtype: 'tabbar',
store: 'InformationTabs',
title: '',
html: ['']
}
]
},
initialize: function() {
var items = [];
Ext.getStore('InformationTabs').each(function(rec) {
items.push({
title: rec.get('title'),
html: rec.get('text')
});
});
this.setItems(items);
this.callParent();
} });
screenshot: http://oi41.tinypic.com/2gsn53p.jpg
Since the store is dynamic, you won't be able to do the full definition in your static config block. You could put the tab creation into the initialize method, something like this:
Ext.define('***', {
extend: 'Ext.tab.Panel',
xtype: 'informationsTabs',
config: {
title: 'InformationTabs',
layout: 'fit',
items: [
{
xtype: 'list',
store: 'InformationTabs',
itemTpl: '{title}, {text}'
}
]
},
initialize: function() {
var items = [];
Ext.getStore('InformationTabs').each(function(rec) {
items.push({
title: rec.get('title'),
html: rec.get('text')
});
});
this.setItems(items);
this.callParent();
}
});
I have been trying to add a custom class into one of my views but when I run the application, I get an error in the console log "Cannot create an instance of unrecognized alias: widget.[object Object]". My code is as follows:
SubCategoryListView.js
Ext.define('RestaurantGlobal.view.SubCategoryListView',{
extend: 'Ext.List',
xtype: 'SubCategoryListView',
requires: ['RestaurantGlobal.store.ItemColumnsStore'],
config:{
items:[
{
xtype: Ext.create('Ext.List', {
fullscreen: true,
items: [{
xtype: 'toolbar',
docked: 'top',
ui: 'neutral',
items: [
{
text:'Veg',
align :'center',
handler: function () {
var sto = Ext.create('RestaurantGlobal.store.ItemColumnsStore');
// clear all existing filters
sto.clearFilter();
sto.filter('Info2', 'False');
}
},
{
text:'Non-Veg',
align :'center',
handler: function () {
var sto = Ext.create('RestaurantGlobal.store.ItemColumnsStore');
// clear all existing filters
sto.clearFilter();
sto.filter('Info2', 'True');
}
},
],
store: 'RestaurantGlobal.store.ItemColumnsStore',
itemTpl: ['{Name} {Image}']
}],
}),
}
]
}
});
SubCategories.js
Ext.define('RestaurantGlobal.view.SubCategories', {
extend: 'Ext.Panel',
requires : ['RestaurantGlobal.view.SubCategoryListView'],
config: {
styleHtmlCls: 'maincontainer',
styleHtmlContent: true,
layout: {
type: 'vbox'
},
items: [
{
xtype: 'titlebar',
flex: 0.5,
docked: 'top',
title: 'Category Name'
},
{
xtype: 'SubCategoryListView',
},
{
xtype: 'container',
items: [
{
xtype: 'button',
docked: 'bottom',
margin: '0 0 0 0',
text: 'Place Order'
}
]
}
]
}
});
Please help me in this regard. Also, is there a way to filter a single store to display them into 2 tabs in the same tabpanel?
I am not using tab panel in this case.
The culprit is this:
xtype: Ext.create('Ext.List', {
xtype must be a string.
You can theoritically put a component instance directly in the items:
items:[
Ext.create('Ext.List', {
fullscreen: true,
items: [{
xtype: 'toolbar',
docked: 'top',
ui: 'neutral',
items: [
{
text:'Veg',
align :'center',
handler: function () {
var sto = Ext.create('RestaurantGlobal.store.ItemColumnsStore');
// clear all existing filters
sto.clearFilter();
sto.filter('Info2', 'False');
}
},
{
text:'Non-Veg',
align :'center',
handler: function () {
var sto = Ext.create('RestaurantGlobal.store.ItemColumnsStore');
// clear all existing filters
sto.clearFilter();
sto.filter('Info2', 'True');
}
},
],
store: 'RestaurantGlobal.store.ItemColumnsStore',
itemTpl: ['{Name} {Image}']
}],
}
]
But in the context of a class definition that would really be ill inspired because this same component instance would be used by every instance you create of your class. Most probably resulting in a lot of problems...
In case you really need to create the component instance yourself, because you can't simply declare its configuration, do it by overriding the initComponent method, and create your component in there. The initComponent method will be called for each new instance of your class, so each one will have its own instance of the child component (sorry, I know that makes a lot of repetitions of the word "instance").
Anyway, it seems that what you are really trying to do is simply to override the list class:
Ext.define('RestaurantGlobal.view.SubCategoryListView',{
extend: 'Ext.List',
xtype: 'SubCategoryListView',
requires: ['RestaurantGlobal.store.ItemColumnsStore'],
// You class is already a list, just add your custom configuration
// directly to it:
config:{
fullscreen: true,
items: [{
xtype: 'toolbar',
docked: 'top',
ui: 'neutral',
items: [{
text:'Veg',
align :'center',
handler: function () {
var sto = Ext.create('RestaurantGlobal.store.ItemColumnsStore');
// clear all existing filters
sto.clearFilter();
sto.filter('Info2', 'False');
}
},{
text:'Non-Veg',
align :'center',
handler: function () {
var sto = Ext.create('RestaurantGlobal.store.ItemColumnsStore');
// clear all existing filters
sto.clearFilter();
sto.filter('Info2', 'True');
}
}],
store: 'RestaurantGlobal.store.ItemColumnsStore',
itemTpl: ['{Name} {Image}']
}]
}
});
Ext.define('RestaurantGlobal.view.SubCategoryListView',{
extend: 'Ext.List',
*xtype: 'SubCategoryListView',*
The problem is that you used xtype in class definition but it could be alias:
Ext.define('RestaurantGlobal.view.SubCategoryListView',{
extend: 'Ext.List',
alias: 'widget.SubCategoryListView',
and then you can use this class to create list in this case by:
xtype: 'SubCategoryListView'
as you expected.
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.
I'm using, or abusing, Sencha Touch for the first time and I just want to push a list view, when i click a button. Here is my view:
Ext.define('TouchNuts.view.Decision', {
extend: 'Ext.Panel',
xtype: 'decision',
config: {
title: 'Decision',
scrollable: true,
styleHtmlContent: true,
styleHtmlCls: 'Decision',
tpl: '<h2>{name}</h2>, <h3>{description}<h3>, <h4>{price:ellipsis(15)}</h4> <h1>you can do this </h1>',
items: [
{
xtype: 'button',
text: 'SEND',
ui: 'confirm',
docked: 'bottom',
action: 'doSomething'
}
]
}
});
Here is the view I'd like to push:
Ext.define('TouchNuts.view.File', {
extend: 'Ext.Panel',
xtype: 'file',
config: {
title: 'File',
iconCls: 'star',
layout: 'fit',
items: [
{
xtype: 'list',
id: 'file',
store: 'TransactionStore',
itemTpl: '<h2>{name:ellipsis(15)}</h2>, <h3>{description:ellipsis(8)}<h3>, <h4>{price:ellipsis(15)}</h4>',
itemCls: 'SummaryItems'
}
]
}
});
And here is my controller:
Ext.define('TouchNuts.controller.doSomething', {
extend: 'Ext.app.Controller',
config: {
refs: {
},
control: {
'button[action=doSomething]' : {
tap: function() {
getMainView('TouchNuts.view.Decision').push('TouchNuts.view.File');
}
}
}
}
});
I'm pretty good with HTML, CSS, and jQuery, but new to JS and totally clueless when it comes to Sencha so any advice is appreciated.
It is good to give your views an itemId inorder to reference them in your controller. So for instance:
TouchNuts.view.Decision can have an itemId:decisionPanel
and
TouchNuts.view.File can have an itemId:filePanel
Now in your Controller you would do this:
...
config: {
refs: {
decisionPanel: {
autocreate: true,
selector: '#decisionPanel',
xtype: 'decision'
},
filePanel: {
autocreate: true,
selector: '#filePanel',
xtype: 'file'
}
},
control: {
'button[action=doSomething]' : {
tap: 'onButtonTap'
}
}
onButtonTap : function(button, e, options) {
var me = this;
Ext.Viewport.setActiveItem(me.getDecisionPanel());
}
...
You will notice that I used getDecisionPanel() to get the decisionPanel view. This is because a getter function is automatically generated for each ref you specify and in order to access it, you new to use get+ the Capitalized ref name.
More info here: http://docs.sencha.com/touch/2-1/#!/api/Ext.app.Controller
Instead of
getMainView('TouchNuts.view.Decision').push('TouchNuts.view.File');
You have to create the view first and then push it to view
getMainView('TouchNuts.view.Decision').push(Ext.create('TouchNuts.view.File'));