I am new to sencha. Almost spent 2 day to understand sencha routing/history support to implement android back button. but ended up with blank screen always although navigation is working. Please help me to find out what wrong am i doing or what is wrong with my application architecture.
app.js
Ext.application({
name: "WorkFlow",
models: [],
stores: [],
controllers: ["WFController"],
views: ["LoginForm","WorkList"],
launch: function () {
var loginForm = {
xtype: "loginform"
};
var workList = {
xtype: "worklist"
};
Ext.Viewport.add([loginForm,workList]);
// set up a listener to handle the back button for Android
if (Ext.os.is('Android')) {
document.addEventListener("backbutton", Ext.bind(onBackKeyDown, this), false);
function onBackKeyDown(e) {
e.preventDefault();
// you are at the home screen
if (Ext.Viewport.getActiveItem().xtype == loginForm.xtype ) {
navigator.app.exitApp();
}else {
this.getApplication().getHistory().add(Ext.create('Ext.app.Action', {
url: 'loginForm'
}));
}
}
}
}
});
LoginForm.js
var formPanel = null;
Ext.define("WorkFlow.view.LoginForm", {
extend: "Ext.form.Panel",
alias: "widget.loginform",
initialize: function () {
this.callParent(arguments);
formPanel = Ext.create('Ext.form.Panel', {
fullscreen: true,
items: [{
xtype: 'titlebar',
title: 'Login',
docked: 'top'
},
{
xtype: 'fieldset',
items: [
{
xtype: 'textfield',
name : 'username',
label: 'Username',
},
{
xtype: 'passwordfield',
name : 'password',
label: 'Password',
},
{
xtype: 'textfield',
name : 'deviceId',
label: 'Device Id',
}
]
}]
});
formPanel.add({
xtype: 'toolbar',
docked: 'bottom',
layout: { pack: 'center' },
items: [
{
xtype: 'button',
text: 'Login',
handler: this.onLoginTap,
scope: this
},
{
xtype: 'button',
text: 'Cancel',
handler: function() {
formPanel.reset();
}
}
]
});
},
onLoginTap: function() {
this.fireEvent("loginCommand", this);
},
});
WorkList.js
Ext.define("WorkFlow.view.WorkList", {
extend: "Ext.form.Panel",
alias: "widget.worklist",
config:{
html: 'This is worklist...',
}
});
WFController.js
Ext.define("WorkFlow.controller.WFController", {
extend: "Ext.app.Controller",
config: {
refs: {
loginForm: "loginform",
workList: "worklist",
},
control: {
loginForm: {
loginCommand: "onLoginCommand",
}
},
routes: {
'loginForm': 'activateLoginFormPage'
}
},
activateLoginFormPage: function(){
Ext.Viewport.animateActiveItem(this.getLoginForm(), this.slideRightTransition);
},
slideLeftTransition: { type: 'slide', direction: 'left' },
slideRightTransition: { type: 'slide', direction: 'right' },
onLoginCommand: function () {
var values = formPanel.getValues();
window.plugins.AuthPlugin.authenticate(values.username,values.passwordvalues.deviceId,values,
function loginCallBack(result){
if(result=="PASSWORD_MATCH"){
loginForm.onLoginSuccess();
}
});
},
onLoginSuccess: function(){
this.getApplication().getHistory().add(Ext.create('Ext.app.Action', {
url: 'loginFormroute/workList'
}));
Ext.Viewport.animateActiveItem(this.getWorkList(), this.slideRightTransition);
},
launch: function () {
},
init: function () {
}
});
Not totally sure of what you are trying to accomplish, but if it is just regular navigation (press back to return to previous tab etc.) then you do not need to bind anything to the android back button. You should use routes and create a history item for every step the user takes.
Example: I have an app with two tabs, in one of the tabs there is a list of locations and in the second one there is a map with the same locations marked. Pressing on wither a list item or a location in the map generates the same details screen. So this is what I got to get this to work:
Routes:
routes: {
'tab/:tabId': 'gotoTab',
'details/:stnId': 'viewDetails'
},
Important part: ensure that you create history items for each step, I basically have two in this app, one for changing tabs and one for opening a details page.
So, tabs:
//If I change to the 'map' tab, it will navigate the browser to myapp.com/#tab/map
// and therefore creating a history item.
onTabpanelActiveItemChange: function(container, value, oldValue, options) {
this.getApplication().getHistory().add(new Ext.app.Action({
url: 'tab/' + value.id
}), true);
},
Similar for my details page, only it is a function that is called from two seperate handlers (one for the list and one for the map):
showDetails: function(record, staticUrl, doUpdate) {
/*some logic stripped out*/
this.getApplication().getHistory().add(new Ext.app.Action({
url: 'details/' + record.data.id
}), true);
}
After this you are more or less ready to go, if you can guarantee that users always start at the main page. If you enable deep-linking etc. than you will need to restore a state for those links. e.g. a #/tab/map/ link should open the app with the map tab active.
If we take my details page as an example, we have a few things to do. First of all re-create history (press back on details page returns to tab-list by default in my app) and then ensure that stores are loaded and so on.
So as a final example, my viewDetails route:
var store = Ext.StoreManager.get("dcStations");
//recreate history
this.getApplication().getHistory().add(new Ext.app.Action({
url: 'tab/list'
}), true);
this.getApplication().getHistory().add(new Ext.app.Action({
url: 'details/' + stnId
}), true);
//make sure the store is loaded, then show the details page with passed id
store.on("load", function() {
this.showDetails(Ext.StoreManager.get("dcStations").getById(stnId));
}, this);
Hope that this boosts your efforts in getting started with routes and history management
Related
I want to store the login form details in the database .for that,i wrote the following code .
In my view code
Ext.define('SampleForm.view.LoginForm', {
extend: 'Ext.form.Panel',
//id:'loginform',
requires:[
'Ext.field.Email',
'Ext.field.Password'
],
config: {
fullscreen: true,
layout:{
type:'vbox'
},
items: [
{
xtype: 'fieldset',
title: 'Login',
id: 'loginform',
items: [
{
xtype:'textfield',
label:'Name',
name:'name'
},
{
xtype: 'emailfield',
name: 'email',
label: 'Email'
},
{
xtype: 'passwordfield',
name: 'password',
label: 'Password'
}
]
},
{
xtype: 'button',
width: '30%',
text: 'Login',
ui: 'confirm',
action:'btnSubmitLogin'
}
]
}
});
In controller
Ext.define("SampleForm.controller.LoginForm", {
extend: "Ext.app.Controller",
config: {
view: 'SampleForm.view.LoginForm',
refs: [
{
loginForm: '#loginform',
Selector: '#loginform'
}
],
control: {
'button[action=btnSubmitLogin]': {
tap: "onSubmitLogin"
}
}
},
onSubmitLogin: function () {
alert('Form Submitted successfully');
console.log("test");
var values = this.getloginform();
/* Ext.Ajax.request({
url: 'http://www.servername.com/login.php',
params: values,
success: function(response){
var text = response.responseText;
Ext.Msg.alert('Success', text);
}
failure : function(response) {
Ext.Msg.alert('Error','Error while submitting the form');
console.log(response.responseText);
}
});*/
form.submit({
url:"http://localhost/sencha2011/form/login.php"
});
},
launch: function () {
this.callParent();
console.log("LoginForm launch");
},
init: function () {
this.callParent();
console.log("LoginForm init");
}
});
when i click the submit button,alert message coming,but values aren't stored in the database.and in console im getting this error,Uncaught TypeError: Object [object Object] has no method 'getloginform'.
Can anyone help me to how to insert the values in the db.
Javascript is case-sensitive. From Sencha Touch docs:
These getter functions are generated based on the refs you define and
always follow the same format - 'get' followed by the capitalized ref
name.
To use the getter method for ref, loginForm, and to get the form values use:
var values = this.getLoginForm().getValues();
Back Ground : I am working on an MVC application using sencha touch 2. I am working on a page which has two tabs. Inside the first tab, I have a button inside a title bar.
Issue : I am not able to call anyother function from the button handler. I think, there is an issue with the scope of the calling function.
Here is my code.
Ext.define('WUPOC.view.WUHomePage', {
extend: 'Ext.TabPanel',
requires:['Ext.TitleBar','Ext.dataview.List','Ext.data.proxy.JsonP'],
alias: 'widget.wuHomePageView',
config: {
fullscreen: true,
defaults: {
styleHtmlContent: true
},
items: [{
title: 'Home',
iconCls: 'home',
items: [{
xtype: 'titlebar',
title: 'Hello',
docked: 'top',
items: [{
xtype: 'button',
text: 'LogOut',
ui: 'action',
itemId: 'newButton',
align: 'right',
handler : function(btn){
console.log('LogOut is tapped'); // This is printed
this.up.onNewButtonTap(); // Throws error
}
}],
}],
}, {
title: 'Contact',
iconCls: 'user',
html: 'Contact Screen'
}]
},
onNewButtonTap: function () {
alert('newNoteCommand');
},
});
I am getting the error as below.
Uncaught TypeError: Object function (selector) {
var result = this.parent;
if (selector) {
for (; result; result = result.parent) {
if (Ext.ComponentQuery.is(result, selector)) {
return result;
}
}
}
return result;
} has no method 'onNewButtonTap'
I think there is an issue with setting the scope of a button. Kindly help.
Thank you
First, up is a function so you need to call it this way :
this.up();
Then this.up() would only bring to the container of the button, which has no method onNewButtonTap. You could just keep doing up() until you get the right component but this would me more clever to do :
Add an xtype to your view
Use this xtype as a selector in the up function : this.up('myXType').onNewButtonTap();
Example
Hope this helps
I have a Main view in which i create three tabs, on click login tab a login form open
after login success, i need to load another view (landing) in same login tabpanel..I have used the following lines of code to load the view but it doesnt opening it in same tabpanel but loading as a independent view. How to open it in same tabpanel.
Main View of application
Ext.define("SenchaTest.view.Main", {
extend: 'Ext.tab.Panel',
requires: [
'Ext.TitleBar',
],
config: {
tabBarPosition: 'bottom',
items: [
{
title: 'Home',
iconCls: 'home',
html: [
'<img src="http://staging.sencha.com/img/sencha.png" />',
'<h1>Welcome to Sencha Touch</h1>',
"<p>This demonstrates how ",
"to use tabs, lists and forms to create a simple app</p>",
'<h2>Sencha Touch (2.0.0)</h2>'
].join("")
},
{
title: 'Log In',
iconCls: 'user',
xtype: 'formpanel',
url: 'contact.php',
layout: 'card',
id:"loginForm",
items: [
{
xtype: 'fieldset',
title: 'Log In',
id:"submitForm",
instructions: 'Enter username and password to login.',
defaults: {
required: true,
labelAlign: 'left',
labelWidth: '45%'
},
items: [
{
xtype: 'textfield',
name : 'username',
label: 'User Name',
allowBlank:false,
useClearIcon: true
}, {
xtype: 'passwordfield',
name : 'password',
label: 'Password',
allowBlank:false,
useClearIcon: false
},{
xtype: 'button',
text: 'Submit',
ui: 'confirm',
id: 'btnSubmitLogin'
// this.up('formpanel').submit();
}]
}
]
}
]
}
});
Code for Controller
Ext.define("SenchaTest.controller.LoginForm", {
extend : "Ext.app.Controller",
config : {
refs : {
btnSubmitLogin : "#btnSubmitLogin",
LoginForm : '#loginForm'
},
control : {
btnSubmitLogin : {
tap : "onSubmitLogin"
}
}
},
onSubmitLogin : function(btn) {
alert("onSubmitLogin");
console.log("onSubmitLogin");
var values = this.getLoginForm().getValues();
//alert(values.username);
//alert(values.password);
Ext.util.JSONP.request({
url:'http://localhost:8092/returnjson.ashx',
params:{ callback:'callback',uname:values.username,password:values.password},
callbackKey: 'callback',
success: function (result,request)
{
if(result.status==true)
{
alert("Welcome " + result.UserName);
Ext.Viewport.setActiveItem(Ext.create('SenchaTest.view.Landing'));
}
else
{
alert("Username or Password is incorrect");
return;
}
console.log(result.UserName);
console.log(result);
alert(result);
// Handle error logic
if (result.error) {
alert(response.error);
return;
}
}
});
},
launch : function() {
this.callParent();
console.log("LoginForm launch");
Ext.Viewport.add(Ext.create('SenchaTest.view.Landing'));
},
init : function() {
this.callParent();
console.log("LoginForm init");
}
});
View to load after login landing
Ext.define("SenchaTest.view.Landing", {
extend: "Ext.Container",
xtype: 'landingScreen',
requires: [
"SenchaTest.view.Main"
],
config: {
html: "Welcome to my app"
}
});
i have used...
Ext.Viewport.setActiveItem(Ext.create('SenchaTest.view.Landing'));
to load landing view but it does not load in same tab but as a independent page.
Please Help on this.
The following code allows you to extend Sencha Touch with a 'replace' function that allows you to dynamically swap two view components within the same panel (I believe that is what you are trying to do):
http://www.sencha.com/forum/showthread.php?134909-Replace-component-function&langid=4
An alternative solution (not recommended) is to create a third, but hidden, tab panel ('Landing'), then create and show it on successfully login, while simultaneously hiding the login tab panel.
i have four separete view, adding these four view in single tabview as shown below.
Tab View Code:
Ext.define("SLS.BRND.WEB.view.MainTabbarView", {
extend: 'Ext.tab.Panel',
xtype: 'MainTabbarView',
requires: ['Ext.data.proxy.JsonP', 'Ext.TitleBar', 'Ext.Video', 'SLS.BRND.WEB.view.GallerysView', 'SLS.BRND.WEB.view.FloorView'],
config: {
tabBarPosition: 'bottom',
items: [
{
xclass: "SLS.BRND.WEB.view.GlobalNavigationView",
docked: "top",
scrollable: false
},
{
xclass: 'SLS.BRND.WEB.view.ApartmentView'
},
{
xclass: 'SLS.BRND.WEB.view.SpecificationView'
},
{
xclass: 'SLS.BRND.WEB.view.FloorView'
},
{
xclass: 'SLS.BRND.WEB.view.GallerysView'
}
]
}
});
In controller onbuttontap function i am calling above 'MainTabbarView' page as shown below. i have set setActiveItem(0); to display first tabitem among four i.e (xclass: 'SLS.BRND.WEB.view.ApartmentView'). when i set like this setActiveItem(0) it will dispaly first view page but without data(blank screen).if i set like this setActiveItem(1), it will dispaly second view page with data. then i thought may be problem in first page, so i have changed order of page view in 'MainTabbarView'. again i set setActiveItem(0) then it showing active page but without data. i have keep on changed setActiveItem(0) to 1,2,3 its working fine and also data displaying. but for the setActiveItem(0) data is not displaying. can any help me . how to resolve this issue. thank you
Controller Code :
Ext.define("SLS.BRND.WEB.controller.ApartmentController", {
extend: "Ext.app.Controller",
requires: ['Ext.data.proxy.JsonP'],
config: {
refs: {
projectsPage: "projectspage",
mainTabbarView: "MainTabbarView",
},
control: {
projectsPage: {
BtnApartments: "onAptButtonTap"
}
}
},
onAptButtonTap: function () {
var ApartmentTabbar = this.getMainTabbarView();
ApartmentTabbar.setActiveItem(0);
Ext.Viewport.animateActiveItem(ApartmentTabbar, this.slideLeftTransition);
},
activateNotesList: function () {
Ext.Viewport.animateActiveItem(this.getHomepage(), this.slideRightTransition);
},
slideRightTransition: { type: 'slide', direction: 'right' },
slideDownTransition: { type: 'flip', direction: 'down' },
slideLeftTransition: { type: 'fade', direction: 'left' }
});
Your onAptButtonTap function is not in the right place, you put it in the config as you should put it after the config like so :
...
config: {
refs: {
projectsPage: "projectspage",
mainTabbarView: "MainTabbarView",
},
control: {
projectsPage: {
BtnApartments: "onAptButtonTap"
}
},
...
},
onAptButtonTap: function () {
var ApartmentTabbar = this.getMainTabbarView();
ApartmentTabbar.setActiveItem(0);
Ext.Viewport.animateActiveItem(ApartmentTabbar, this.slideLeftTransition);
},
...
I am having a very hard time understanding why i can't go back to the previous panel within my application. Enough talk, some code
appsDetails = Ext.extend(Ext.Panel, {
layout: 'fit',
scroll: 'verticall',
initComponent: function() {
this.dockedItems = [{
xtype: 'toolbar',
items: [{
ui: 'back',
scope: 'this',
handler: function() {
console.log(this.ownerCt) //This returns "undefined"
this.ownerCt.setActiveItem(this.prevCard, {
type: 'slide',
reverse: true,
scope: this,
after: function() {
this.destroy();
}
})
}
}]
}];
this.items = [{
styleHtmlContent: true,
tpl: description,
data: this.record.data
}];
appsDetails.superclass.initComponent.call(this);
}
});
I am getting to this view above by using this code below in the previous panel
selection: function(list, index) {
if (index[0] !== undefined) {
var details = new appsDetails({
homeCard: this.appsPanel,
record: index[0],
});
this.setActiveItem(details, {type: 'slide', direction: 'left'})
}
}
I have no problem getting to the desired panel but i can't come back the previous one.
Thx for your help
You are passing a string object with value 'this'. Change this line: scope:'this' in scope:this