Related
I have a quite simple mobile app I want to build with Sencha Touch 2. I have quite a lot of experience with ExtJs, but not really with their MVC architecture. What I want to achieve is :
first a main screen with toolbar and some icons rendered in the middle which are to be used to navigate across the app functionality.
clicking one of the icons should switch to a screen with a scrollable list.
What I'm struggling with is the proper place to define the views, and controllers. As well as should for example the main screen use a controller ? Should I create a viewport manually or not ?
What I have right now, which is not rendering anything apart of the toolbar :
app.js
Ext.application({
name: 'SG',
views: [
'Main',
'MainScreen'
],
launch: function() {
// Destroy the #appLoadingIndicator element
Ext.fly('appLoadingIndicator').destroy();
// Initialize the main view
Ext.Viewport.add(Ext.create('SG.view.Main'));
}
})
Main.js
Ext.define('SG.view.Main', {
extend: 'Ext.Container',
requires: [
'Ext.TitleBar',
'ShopGun.view.MainScreen'
],
config: {
layout : 'fit',
items: [
{
title: 'Welcome',
iconCls: 'home',
position: 'top',
scrollable: true,
items: [
{
docked: 'top',
xtype: 'titlebar',
title: 'SG Alpha 1'
}
Ext.create('SG.view.MainScreen', {
docked: 'bottom'
})
]
}
]
}
});
MainScreen.js
Ext.define('SG.view.MainScreen', {
extend: 'Ext.Container',
xtype: 'mainScreen',
initialize : function(){
Ext.define("MenuIcon", {
extend: "Ext.data.Model",
config: {
fields: [
{name: "Name", type: "string"},
{name: "Icon", type: "string"}
]
}
});
this.store = Ext.create('Ext.data.Store', {
model: 'MenuIcon',
data: [
{
Name: "A",
Icon: "a.png"
},
{
Name: "B",
Icon: "b.png"
}
]
});
this.html = 'foo';
this.callParent(arguments);
}
});
And finally an image of what I'd like to get :
EDIT:
A senchafiddle demo here : http://www.senchafiddle.com/#jSqtV (which is not rendering at all but doesn't throw any errors).
Trying to have a button push to a different view 'new profile' and 'profile page' (second view) Of course I would have authentication, however just trying to get the views correct before implement the controllers and server side.
Having the following errors:
Uncaught ReferenceError: view is not defined Main.js:116
Uncaught ReferenceError: view is not defined Main.js:126
Google only brings back "ext is not defined" responses.
Forgive the shocking coding as this is my first app for my school assignment (please give feedback how to improve this if possible) I understand that the view needs to be defined, however in the Sencha Touch's API is where I got the information.
Thanks for your time.
var pageFilterGame = {
xtype: 'panel',
title: 'Filter Games',
items: [
{
xtype: 'fieldset',
title: 'Filter games to find the perfect one',
instructions: 'Please fill in atleast one field to start.',
items: [
{
xtype: 'selectfield',
label: 'What enviroment will this game be played in',
options: [
{ text: 'Outside on Grass', value: 'grass' },
{ text: 'Outside on Concrete', value: 'concrete' },
{ text: 'Inside', value: 'inside' }
]
},
{
xtype: 'selectfield',
name: 'equipment',
label: 'What equipment do you have',
options: [{text: 'DB form'}]
},
{
xtype: 'numberfield',
name : 'Player Numbers',
label: 'How many players do you have',
minValue: 2,
maxValue: 50
},
{
xtype: 'numberfield',
name: 'avgname',
label: 'Average age of players',
minValue: 2,
maxValue: 99
},
{
xtype: 'selectfield',
label: 'Sort result by:',
options: [
{ text: 'Highest Rated', value: 'rated' },
{ text: 'Equipment', value: 'equipment' },
{ text: 'Alphabetically', value: 'alpha' }
]
},
],
},
{
xtype: 'button',
ui: 'action',
text: 'Filter Games',
action: '',
maxWidth: '150px'
}
]
};
var pageSearch = {
xtype: 'panel',
title: 'Search',
items: [
{
xtype: 'fieldset',
title: 'Search',
items: [
{
xtype: 'searchfield',
label: 'Search',
name: 'search'
}
]
},
{
xtype: 'button',
ui: 'action',
text: 'Search',
action: '',
maxWidth: '100px'
}
]
};
var pageProfileLogin = {
xtype: 'panel',
title: 'My Profile',
items: [
{
xtype: 'fieldset',
title: 'Please login to access your profile',
items: [
{
xtype: 'textfield',
name : 'username',
label: 'Username'
},
{
xtype: 'passwordfield',
name: 'password',
label: 'Password',
clearIcon: false
}
]
},
{
xtype: 'toolbar',
docked: 'bottom',
items: [
{
text: 'Login',
ui: 'confirm',
handler: function() {
view.push({
title: 'Second View',
padding: 10,
})},
},
{
xtype: 'button',
ui: 'action',
text: 'Create New',
handler: function() {
view.push({
title: 'New Profile',
items: [
{
xtype: 'fieldset',
title: 'Please fill in the form to create your profile',
items: [
{
xtype: 'textfield',
name : 'username',
label: 'Username'
},
{
xtype: 'passwordfield',
name: 'password',
label: 'Password',
clearIcon: false
},
{
xtype: 'textfield',
name : 'name',
label: 'Name'
},
],
},
{
xtype: 'toolbar',
docked: 'bottom',
items: [
{
text: 'Login',
ui: 'confirm',
},
]
}
]
});
}
},
]
},
]}
var viewTabConfig = {
xtype: 'tabpanel',
styleHtmlContent: true,
title: 'Get Creative!',
items: [pageFilterGame, pageSearch, pageProfileLogin]
};
var viewDef = {
//
// Another new UI element introduced. This UI element allows one to add multiple panels in a 'stacked' like operation. A
// new panel when pushed into the NavigationView will be displayed along with a back button. When the back button is tapped,
// the visible view is 'popped' and the parent view gets displayed again. See demo in the lecture recording.
//
extend: 'Ext.NavigationView',
id: 'navView',
requires: [
'Ext.TitleBar',
'Ext.Video',
'Ext.field.Password',
'Ext.field.Select',
'Ext.field.Number',
'Ext.field.Search',
'Ext.form.FieldSet',
'Ext.tab.Panel',
'Ext.data.Store',
'Ext.data.reader.Xml'
],
config: {
fullscreen: true,
items: [viewTabConfig]
}
};
Ext.define("a2.view.Main", viewDef);
I had to add extra models and view to the app.js file and it worked fine.
I'm trying to create a Sencha Touch 2 form panel for a model in which one of the fields contains the URL to an image file. If I include a textfield, it'll display the text of the URL correctly, but what I really want is to display the image found at that URL, and I'm not sure how to do that. If I use xtype: image, I think I need a src config, and I'm not sure how to specify that the desired value is in one of the form fields. My view looks like this:
Ext.define("CatalogApp.view.ItemDetailView", {
extend: "Ext.form.Panel",
requires: "Ext.form.FieldSet",
alias: "widget.itemdetailview",
config:{
scrollable:'vertical'
},
initialize: function ()
{
this.callParent(arguments);
var backButton = {
xtype: "button",
ui: "back",
text: "Home",
handler: this.onBackButtonTap,
scope: this
};
var topToolbar = {
xtype: "toolbar",
docked: "top",
title: "Item Detail",
items: [
backButton
]
};
var mainLayout = {
xtype: "container",
layout: 'hbox',
items: [
{
xtype: 'textfield',
width: 200,
name: 'thumbUrl'
},
{
xtype: "fieldset",
flex: 1,
items : [
{
xtype: 'textfield',
name: 'itemNbr',
label: 'Item Nbr',
disabled: true
},
{
xtype: 'textfield',
name: 'itemDesc',
label: 'Item Desc',
disabled: true
}
]
}
]
};
this.add([
topToolbar,
mainLayout
]);
},
onBackButtonTap: function ()
{
console.log("backToHomeCommand");
this.fireEvent("backToHomeCommand", this);
}
});
How can I set up this view to display the image correctly?
You have to define new Sencha component: ImageField
Ext.define('Ext.ux.field.ImageField', {
extend: 'Ext.field.Field',
requires: [
'Ext.Img'
],
xtype: 'imagefield',
config: {
component: {
xtype: 'image'
}
},
updateValue: function(value, oldValue) {
var me = this,
component = me.getComponent();
component.setSrc(value);
},
proxyConfig: {
width: '100%',
height: '100%'
}
});
Than in form:
Ext.define("CatalogApp.view.ItemDetailView", {
extend: "Ext.form.Panel",
requires: "Ext.form.FieldSet",
alias: "widget.itemdetailview",
config:{
scrollable:'vertical'
},
initialize: function ()
{
this.callParent(arguments);
var backButton = {
xtype: "button",
ui: "back",
text: "Home",
handler: this.onBackButtonTap,
scope: this
};
var topToolbar = {
xtype: "toolbar",
docked: "top",
title: "Item Detail",
items: [
backButton
]
};
var mainLayout = {
xtype: "container",
layout: 'hbox',
items: [
{
xtype: 'imagefield', // only this change
width: 200,
height: 150,
name: 'thumbUrl'
},
{
xtype: "fieldset",
flex: 1,
items : [
{
xtype: 'textfield',
name: 'itemNbr',
label: 'Item Nbr',
disabled: true
},
{
xtype: 'textfield',
name: 'itemDesc',
label: 'Item Desc',
disabled: true
}
]
}
]
};
this.add([
topToolbar,
mainLayout
]);
},
onBackButtonTap: function ()
{
console.log("backToHomeCommand");
this.fireEvent("backToHomeCommand", this);
}
});
Cheers, Oleg
I'm having a dumb problem and I would like you to give me a hand.Thanks in advance.
The situatios is as follows: I have 2 wiews (both created with sencha architect 2.0), one for login, and another for general purposes. And I would like to load the second view on successful response when trying to log in, this is, after any successful login. The main problem is that I've tried with Ex.create, Ext.Viewport.add, Ext.Viewport.setActiveItem, but I can't manage to make the second view to appear on screen, the login screen just keeps there and the app does not load the other view. Another thing, I don't have to use a navigation view for this.
Here is the code of my controller, from which I want to load my second view. And as you'll see, I even created a reference of the view, which has autoCreate enabled and has that ID "mainTabPanel":
Ext.define('MyApp.controller.Login', {
extend: 'Ext.app.Controller',
config: {
refs: {
loginButton: {
selector: '#login',
xtype: 'button'
},
username: {
selector: '#user',
xtype: 'textfield'
},
password: {
selector: '#pass',
xtype: 'passwordfield'
},
mainTabPanel: {
selector: '#mainTabPanel',
xtype: 'tabpanel',
autoCreate: true
}
},
control: {
"loginButton": {
tap: 'onLoginButtonTap'
}
}
},
onLoginButtonTap: function(button, e, options) {
Ext.Ajax.request({
url: '../../backend/auth.php',
method: 'POST',
params: {
user: this.getUsername().getValue(),
pass: this.getPassword().getValue()
},
success: function(response) {
var json = Ext.decode(response.responseText);
if (json.type == 'success') {
// LOAD THE DAMN SECOND VIEW HERE!
//var paneltab = Ext.create('MyApp.view.MainTabPanel');
//Ext.Viewport.add(paneltab);
//Ext.Viewport.setActiveItem(this.getMainTabPanel());
} else {
alert(json.value);
}
},
failure: function(response) {
alert('The request failed!');
}
});
}
});
And here is the code of my login view:
Ext.define('MyApp.view.LoginForm', {
extend: 'Ext.form.Panel',
config: {
id: 'loginForm',
ui: 'light',
items: [
{
xtype: 'fieldset',
ui: 'light',
title: 'Log into the system',
items: [
{
xtype: 'textfield',
id: 'user',
label: 'User',
name: 'user'
},
{
xtype: 'passwordfield',
id: 'pass',
label: 'Pass',
name: 'pass'
}
]
},
{
xtype: 'button',
id: 'login',
ui: 'confirm',
text: 'Login'
}
]
}
});
And finally, the code of the view I want to load. This view loads normally if I set it as the Initial View, but does not load when a successful login occurs:
Ext.define('MyApp.view.MainTabPanel', {
extend: 'Ext.tab.Panel',
config: {
id: 'mainTabPanel',
layout: {
animation: 'slide',
type: 'card'
},
items: [
{
xtype: 'container',
layout: {
type: 'vbox'
},
title: 'Tab 1',
iconCls: 'time',
items: [
{
xtype: 'titlebar',
docked: 'top',
title: 'General Report',
items: [
{
xtype: 'button',
iconCls: 'refresh',
iconMask: true,
text: '',
align: 'right'
}
]
},
{
xtype: 'container',
height: 138,
flex: 1,
items: [
{
xtype: 'datepickerfield',
label: 'From',
placeHolder: 'mm/dd/yyyy'
},
{
xtype: 'datepickerfield',
label: 'To',
placeHolder: 'mm/dd/yyyy'
},
{
xtype: 'numberfield',
label: 'Hours'
}
]
},
{
xtype: 'dataview',
ui: 'dark',
itemTpl: [
'<div style="height:50px; background-color: white; margin-bottom: 1px;">',
' <span style="color: #0000FF">{user}</span>',
' <span>{description}</span>',
'</div>'
],
store: 'hoursStore',
flex: 1
}
]
},
{
xtype: 'container',
title: 'Tab 2',
iconCls: 'maps'
},
{
xtype: 'container',
title: 'Tab 3',
iconCls: 'favorites'
}
],
tabBar: {
docked: 'bottom'
}
}
});
Please, I need help... :)
I'm stuck here for like 3 days now and can't figure out what the problem is. Thank you.
Could you post your app.js too?
I'm trying your code here and it load the view as expected. Here is my app.js:
Ext.application({
name: 'MyApp',
requires: [
'Ext.MessageBox'
],
controllers: ['Login'],
views: ['LoginForm','MainTabPanel'],
icon: {
'57': 'resources/icons/Icon.png',
'72': 'resources/icons/Icon~ipad.png',
'114': 'resources/icons/Icon#2x.png',
'144': 'resources/icons/Icon~ipad#2x.png'
},
isIconPrecomposed: true,
startupImage: {
'320x460': 'resources/startup/320x460.jpg',
'640x920': 'resources/startup/640x920.png',
'768x1004': 'resources/startup/768x1004.png',
'748x1024': 'resources/startup/748x1024.png',
'1536x2008': 'resources/startup/1536x2008.png',
'1496x2048': 'resources/startup/1496x2048.png'
},
launch: function() {
// Destroy the #appLoadingIndicator element
Ext.fly('appLoadingIndicator').destroy();
// Initialize the main view
//Ext.Viewport.add(Ext.create('MyApp.view.Main'));
Ext.Viewport.add(Ext.create('MyApp.view.LoginForm'));
},
onUpdated: function() {
Ext.Msg.confirm(
"Application Update",
"This application has just successfully been updated to the latest version. Reload now?",
function(buttonId) {
if (buttonId === 'yes') {
window.location.reload();
}
}
);
}
});
Destroy the login panel, You don't really need it anymore...
success: function(response) {
var json = Ext.decode(response.responseText);
if (json.type == 'success') {
// LOAD THE DAMN SECOND VIEW HERE!
var paneltab = Ext.create('MyApp.view.MainTabPanel');
Ext.getCmp('loginForm').destroy();
Ext.Viewport.add(paneltab);
} else {
alert(json.value);
}
},
There are several problems here:
Your autoCreate rule uses an xtype: 'tabpanel' which will only ever create a vanilla Ext.TabPanel with no items in it. You'd need to assign an xtype attribute to your MyApp.view.MainTabPanel like xtype: 'mainTabPanel' and then use that xtype value in your autoCreate rule.
This then explains why this code won't work since this.getMainTabPanel() will return the wrong object. Simpler would be to just use Ext.Viewport.setActiveItem(paneltab).
In general, you usually don't want assign an id to a view (id: 'mainTabPanel'). Safer to just use an xtype to fetch it. Although you don't need it in this case, avoiding global id's allows you to create multiple instances of a view (or any other class type).
I have a scrolling problem that's driving me crazy. It only happens with card layout, and I tried every possible combination of "scroll" values, withou success.
Here is my situation:
I have an app with a tab panel attached to Viewport
Inside each tab, I need a card layout panel, so I can navigate on each tab independently (each tab is a different section)
The problem is: the scrolling works with simple elements like html div's, but if I try to grab a Ext.DataView OR a Ext.List component and scroll, it does not work properly
Funny thing: if I grab a DataView (or List), move the mouse a little bit and try to scroll, it works
The project is online for you to check: http://gaeti.com/scrollTest/
The code for the troubled card is here:
homeCardStart.js
Ext.regModel('testModel', {
fields: [{
name: 'name',
type: 'string'
}, {
name: 'birthday',
type: 'string'
}, {
name: 'description',
type: 'string'
}]
});
var testStore = new Ext.data.Store({
model: 'testModel',
method: 'GET',
proxy: {
url: 'res/recSample.json',
type: 'ajax',
reader: {
type: 'json',
root: 'items',
record: 'people',
}
}
});
var testData = new Ext.DataView({
tpl: '<tpl for="."><div class="person">{name}<br>{birthday}<br>{description}</div></tpl></div>',
store: testStore,
itemSelector: 'div.person',
scroll: false,
width: 350,
autoHeight: true,
margin: 20,
style: 'border:2px solid magenta'
});
testData.on('render', function () {
testData.store.load();
}, this);
App.views.HomeCardStart = Ext.extend(Ext.Panel, {
title: 'Home Start',
iconCls: 'home',
layout: 'vbox',
scroll: 'vertical',
style: 'background-color: silver',
dockedItems: [{
xtype: 'toolbar',
dock: 'top',
title: 'Home Start'
}],
items: [{
html: 'Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>Test<br>',
style: 'border:2px solid green',
width: 350,
autoHeight: true
},
testData]
});
Ext.reg('homeCardStart', App.views.HomeCardStart);
Viewport.js:
App.views.Viewport = Ext.extend(Ext.TabPanel, {
fullscreen: true,
tabBar: {
dock: 'bottom',
layout: {
pack: 'center'
}
},
id: 'mainTabPanel',
defaults: {
scroll: 'vertical'
},
items: [{
xtype: 'homeCard',
id: 'homeCard',
cls: 'home'
}, {
title: 'Mais',
iconCls: 'more'
}, {
title: 'Mais',
iconCls: 'more'
}, {
title: 'Mais',
iconCls: 'more'
}, {
title: 'Mais',
iconCls: 'more'
}]
});
HomeCard.js:
App.views.HomeCard = Ext.extend(Ext.Panel, {
title: 'Home',
iconCls: 'home',
layout: 'card',
width: '100%',
height: '100%',
style: 'background-color: green;',
items: [{
xtype: 'homeCardStart'
}, {
xtype: 'panel',
title: 'Another card',
style: 'background-color: pink'
}]
});
Ext.reg('homeCard', App.views.HomeCard);
What can be happening? Is it a bug? It only happens with card panel (the same bug occurs without a main tab panel outside)
Thanks!
Leo
The problem you are having is that you are nesting scrollable panels. In your tab panel you set the defaults to always add scroll to each card, and then within that card, the dataview is also scrollable.
To fix the issue, you should either turn scrolling off on your dataview, or remove scrolling on your card item. You cannot have both.