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'));
Related
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'
});
In sencha touch application I got views, one of them contains a list.
If I switch from the view which contains the list to another view and back, the list itemtap event not fires again.
My view with the list:
Ext.define('app.view.ItemList', {
extend: 'Ext.navigation.View',
xtype: 'listitems',
config: {
title: 'List',
items: [
{
xtype: 'toolbar',
ui: 'light',
docked: 'top',
title: 'List',
items: [
{
xtype: 'button',
text: 'Back',
ui: 'back',
handler: function() {
Ext.Viewport.animateActiveItem({xtype:'main'}, {type:'slide'});
}
},
]
},
{
xtype: 'list',
itemTpl: '{"name"}',
store: {
autoLoad: true,
fields: ['name', 'email'],
proxy: {
type: 'rest',
url: 'data/data.json',
reader: {
type: 'json'
}
}
}
}]
},
initialize: function() {
this.callParent();
}
})
Controller for this:
Ext.define('app.controller.Main', {
extend: 'Ext.app.Controller',
config: {
refs: {
listitems: 'listitems'
},
control: {
'listitems list': {
itemtap: 'showItem',
}
}
},
showItem: function(list, index, element, record) {
this.getItemlist().push({
xtype: 'panel',
title: record.get('name'),
html: [
"<b>Name:</b> " + record.get('name') +
"<b>Email:</b> " + record.get('email')
],
scrollable: true,
styleHtmlContent: true
})
}
})
I tried it also with id, itemId, nothing worked.
How could I solve this?
Please try sth like this:
this.getItemlist().push(
Ext.create('Ext.panel.Panel,{
title: record.get('name'),
html: [
"<b>Name:</b> " + record.get('name') +
"<b>Email:</b> " + record.get('email')
],
scrollable: true,
styleHtmlContent: true
})
)
and don't forget to use getItemlist().pop() when back button is clicked! In my app, the back button did not (or not always) remove the view on top of the stack. It gets even worse when adding loadmasks and ActionSheets.
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 have a view. I'm trying to attach an onchange listener for an input field. I know how to do it with a textfield but I have a very specific setup I need to use html fields. How can I get the listener below to work, so if i change text in the field, I get some output in my console.
Ext.define('A.view.Viewa', {
xtype: 'Viewa',
extend: 'Ext.Panel',
config: {
title: 'Title',
layout: {
type: 'fit'
},
items: [
{
styleHtmlContent: true,
scrollable: true,
items: [
],
html: [
"<input type='text' value='changeme' id='changetext'/>"
].join("")
}
],
listeners : {
change : {
fn: function() {
console.log("Yes it works!!");
},
delegate : '#changetext',
element : 'element'
}
}
}
});
I tried it with your change listener but that does not work. The keyup listener seems to work fine.
Ext.define('A.view.Viewa', {
extend: 'Ext.Panel',
xtype: 'Viewa',
config: {
html: '<input type="text" value="changeme" id="changetext"/>',
styleHtmlContent: true,
scrollable: true,
layout: {
type: 'fit'
},
listeners: {
keyup: {
fn: function() {
console.log("Yes it works!!");
},
delegate: '#changetext',
element: 'element'
}
},
items: [
{
xtype: 'titlebar',
docked: 'top',
title: 'Title'
}
]
}
});
I'm trying to switch panels when tapping 'login' in a toolbar.
My controller gets the event and I switch by adding and setting the active item to the panel I want.. however, the screen stays blank (and there are no debug errors).
This is the code of my panel, any idea what the mistake might be?
Ext.define('App.view.LoginView', {
extend: 'Ext.Panel',
xtype: 'loginpanel',
alias: 'widget.loginView',
fullscreen: true,
layout: 'fit',
items: [
{
xtype: 'TopToolBar'
},
{
xtype: 'formpanel',
items: [
{
xtype: 'fieldset',
title: 'Login',
instructions: 'Have a great day!',
items: [
{
xtype: 'emailfield',
name: 'email',
label: 'Email'
},
{
xtype: 'passwordfield',
name: 'password',
label: 'Password'
}
]
},
{
xtype: 'button',
text: 'Login',
ui: 'confirm',
handler: function()
{
this.up('loginpanel').submit();
}
}
]
}]})
The code of my toolbar class:
Ext.define('App.view.TopToolBar', {
extend: 'Ext.Toolbar',
xtype: 'TopToolBar',
dock: 'top',
initialize: function() {
var loginButton = {
xtype: 'button',
text: 'Login',
ui: 'action',
handler: this.onLoginTap,
scope: this
};
this.add(loginButton);
},
onLoginTap: function(){
console.log('login tap');
this.fireEvent('loginBtnHandler', this);
}})
Define classes with Ext.define.
Ext.define('My.Toolbar', {
extend: 'Ext.Toolbar',
alias: 'widget.mytoolbar'
//configuration
});
Create(Instantiate) classes with Ext.create
var tlb= Ext.create('My.Toolbar', {
//configuration
});