Multiple tap issue in navigation view - sencha-touch-2

I am using Navigation view. Initially it has one item(view) that contains a button. On tapping this button, a second view pushes in the navigation view. If the user intentionally or by accident double tap the button, it pushes second view two times. How can i solve this problem?
I have tried the buffer configuration as specified in this link http://docs.sencha.com/touch/2.3.0/#!/guide/events but problem with this solution is that it invokes the listener after the buffer time even on the first tap.
Here is sample code to demonstrate the issue.
Navigation View
Ext.define('Many.view.Main', {
extend: 'Ext.navigation.View',
xtype: 'main',
config: {
items: [
{
xtype:'firstView'
}
]
}
});
First View
Ext.define('Many.view.FirstView', {
extend: 'Ext.Panel',
xtype: 'firstView',
config: {
title: 'First View',
items: [
{
xtype: 'button',
id:'myButton',
text: 'Push Second View'
}
]
}
});
Second View
Ext.define('Many.view.SecondView', {
extend: 'Ext.Panel',
xtype: 'secondView',
config: {
items: [
{
docked: 'top',
xtype: 'titlebar',
title: 'Second View'
}
]
}
});
Controller
Ext.define('Many.controller.Main', {
extend : 'Ext.app.Controller',
config : {
refs : {
myNavigationView : 'main',
myButton :'main #myButton'
},
control : {
myButton : {
tap : 'pushSecondView'
}
}
},
pushSecondView: function () {
var secondView = Ext.create('Many.view.SecondView');
this.getMyNavigationView().push(secondView);
}
});

Just add a condition whether that view exists in the viewport or not.
Add a reference in the controller like this:-
refs : {
myNavigationView : 'main',
myButton :'main #myButton',
secondView : 'secondView'
}
And add the condition:-
pushSecondView: function () {
if(!this.getSecondView()){
var secondView = Ext.create('Many.view.SecondView');
this.getMyNavigationView().push(secondView);
}
}

Here's how I do it:
/**
* This method will be called from every item in the app that can be double tapped to push multiple items.
*
* #returns {Boolean}
*/
ENSURE_NO_DOUBLE_TAP : function(classNameToPush) {
if (Ext.getClassName(Ext.getCmp('navigationview').getActiveItem()) == classNameToPush) {
console.log("Prevented DoubleTap.");
return false;
}
return true;
}
Then from any controller that uses navigationView.push({'theViewImPushing'}):
if (!ENSURE_NO_DOUBLE_TAP('App.view.TheViewImPushing')) {
return;
}
I keep a Statics singleton class around to call the ENSURE_NO_DOUBLE_TAP method from...but you could use it wherever fits.

Related

Push Pop operations in Naviagtion view Sencha Touch

I am trying to use a navigation view and execute the push and pop operations over it , But cant find where exactly i can define the object view , which would be used for view.push and view.pop.
cause i am getting this error that view isnt defined !
if trying to define Third_Navigate into a var view like
var view = Ext.define('MyFirstApp.view.Third_Naviagte', { .. });
then i am getting the error view.push isnt defined. Help.
Ext.define('MyFirstApp.view.Third_Naviagte', {
extend: 'Ext.navigation.View',
xtype: 'navigationview',
//itemId:'navView',
//we only give it one item by default, which will be the only item in the 'stack' when it loads
config:{
items: [
{
//items can have titles
title: 'Navigation View',
padding: 10,
//inside this first item we are going to add a button
items: [
{
xtype: 'button',
text: 'Push another view!',
handler: function() {
//when someone taps this button, it will push another view into stack
view.push({
//this one also has a title
title: 'Second View',
padding: 10,
//once again, this view has one button
items: [
{
xtype: 'button',
text: 'Pop this view!',
handler: function() {
//and when you press this button, it will pop the current view (this) out of the stack
view.pop();
}
}
]
});
}
}
]
}
]}
});
The reason your example with var view = Ext.define(...); is not working is because Ext.define unlike Ext.create doesn't return an Object instance. It should be var view = Ext.create(...);.
Alternative way to do it would be using the up method used for selecting ancestors.
In your handler function use this to get the button instance and from there you can select the navigationview like so:
handler: function() {
var view = this.up('navigationview');
view.push({
title: 'Second View',
padding: 10,
items: [
{
xtype: 'button',
text: 'Pop this view!',
handler: function() {
view.pop();
}
}
]
});
}

How to use the html id in sencha touch

I am new to sencha touch. I am creating a app in which i am using a html . When that span is clicked a function in controller should be called . I have attached the view and controller with this question.
View
Ext.define('SlideNav.view.Viewport', {
extend: 'Ext.Container',
xtype: 'app_viewport',
requires: [
'Ext.TitleBar'
],
config: {
fullscreen: true,
layout: 'hbox',
items : [
{
docked: 'top',
xtype: 'panel',
height: 40,
style:'background:white ;height:40px;color:black',
items:[
{
html:'<div><span style="padding:10px;position:absolute" id="TopNews">Top News</span><span style="padding:13px;position:absolute;right:10px;font-size:12px">MORE</span></div>'
}
],
listeners: {
initialize:function(){
this.fireEvent('onPopulateDashBoardData', this);
}
/* tap: {
fn: function(event, el){ console.log("tapped!");
this.fireEvent('onPopulateDashBoardData', this);
},
element: 'element',
delegate: '#TopNews'
}*/
}
},
{
xtype : 'main',
cls: 'slide',
// Needed to fit the whole content
width: '100%'
}, {
xtype : 'navigation',
width : 250
}]
}
});
controller.js
Ext.define('SlideNav.controller.App',{
extend: 'Ext.app.Controller',
config:{
refs:{
app_viewport: 'app_viewport',
main : 'main',
navigation : 'navigation',
navBtn : 'button[name="nav_btn"]',
},
control : {
app_viewport:{
onPopulateDashBoardData:'toggleNav'
},
navBtn : {
tap : 'toggleNav'
},
navigation : {
itemtap : function(list, index, target, record){
this.toggleNav();
console.log(record);
alert(record._data.title);
}
}
}
},
/**
* Toggle the slide navogation view
*/
toggleNav : function(){
var me = this,
mainEl = me.getMain().element;
console.log('hai');
if (mainEl.hasCls('out')) {
mainEl.removeCls('out').addCls('in');
me.getMain().setMasked(false);
} else {
mainEl.removeCls('in').addCls('out');
me.getMain().setMasked(true);
}
}
});
In the above question , i want to click a text with id TopNews from and want to call a function toggleNav in controller. I tried to fire a event with the name onPopulateDashBoardData and tried to use that event in the controller. But it is also not working . What should you know.
The way you are referring the text is wrong.
Do this:-
items:[{
name: 'top_news', // add this name for referring
html:'<div><span style="padding:10px;position:absolute" id="TopNews">Top News</span><span style="padding:13px;position:absolute;right:10px;font-size:12px">MORE</span></div>'
}]
Controller:-
refs:{
menu: container[name='top_news']
},
control : {
menu : {
initialize: function(container) {
container.element.on({
tap: 'toggleNav',
scope: this,
delegate: '#TopNews'
});
}
}
}

What is the correct method for dynamically setting titles for views in Sencha Touch 2

I am currently setting view titles in a sencha touch 2 view like so:
initialize: function() {
this.callParent();
var translator = Ext.create('MyApp.util.Translation');
this.config.title = translator.translateData('pagetitle.detail');
}
The translation class just looks up a string from a javascript object based ont the key provided in the translator.translateData function.
With this approach when the view has loaded the title shifts slightly to right (40 px or so).
I have also tried placing this in a view listener activate with similar results.
What is the correct method for dynamically setting a view title in ST2?
You can do this way via the Controller
Ext.define('MyApp.controller.MyController', {
extend: 'Ext.app.Controller',
config: {
refs: {
titlebar: {
autoCreate: true,
selector: '#mytitlebar',
xtype: 'titlebar'
}
},
control: {
"titlebar#mytitlebar": {
initialize: 'onTitlebarInitialize'
}
}
},
onTitlebarInitialize: function(component, options) {
var me = this;
me.getTitlebar().setTitle("Second Title");
// OR IN YOUR CASE:
var translator = Ext.create('MyApp.util.Translation');
me.getTitlebar().setTitle(translator.translateData('pagetitle.detail'));
}
});
Views:
Ext.define('MyApp.view.MyContainer', {
extend: 'Ext.Container',
config: {
items: [
{
xtype: 'titlebar',
docked: 'top',
itemId: 'mytitlebar',
title: 'First Title'
}
]
}
});

How to switch a view container using Sencha Touch?

How do I switch views in Sencha Touch? Currently I have a new view being shown, but it looks like it overlays onto the existing one. I think I need to hide the previous or destroy it. I was thinking of maybe using Ext.getCmp("noteslist") but this returns 'undefined' when trying to get the current container. Is this the recommended way of navigating between views or is there a better way?
App
Ext.application({
name: "NotesApp",
controllers: ["NotesController", "TestController"],
views: ["NotesListContainer"],
launch: function () {
var notesListContainer = Ext.create("NotesApp.view.NotesListContainer");
Ext.Viewport.add(notesListContainer);
}
});
Controller:
Ext.define("NotesApp.controller.NotesController", {
extend: "Ext.app.Controller",
views: [
"TestListContainer"
],
config: {
refs: {
newNoteBtn: "#new-note-btn",
saveNoteBtn: "#save-note-btn",
},
control: {
newNoteBtn: {
tap: "onNewNote"
},
saveNoteBtn: {
tap: "onSaveNote"
}
}
},
onNewNote: function () {
console.log("onNewNote");
},
onSaveNote: function () {
console.log("onSaveNote");
Ext.Viewport.add({xtype:'testlist'}).show();
// How do I remove the current one?....
},
launch: function () {
this.callParent();
console.log("launch");
},
init: function () {
this.callParent();
console.log("init");
}
});
View
Ext.define("NotesApp.view.NotesListContainer", {
extend: "Ext.Container",
config: {
items: [{
xtype: "toolbar",
docked: "top",
title: "My Notes",
items: [{
xtype: "spacer"
}, {
xtype: "button",
text: "New",
ui: "action",
id:"new-note-btn"
}, {
xtype: "button",
text: "Save",
ui: "action",
id:"save-note-btn"
}]
}]
}
Using Ext.Viewport.add you only add component to viewport, but not set it as active item. You can use Ext.Viewport.setActiveItem for add component and set it as active item in one call.
Example:
//1
Ext.Viewport.setActiveItem({xtype:'testlist'});
//or 2
//Create and add to viewport
Ext.Viewport.add({xtype:'testlist'});
//set active item by index
Ext.Viewport.setActiveItem(1);
//or 3
var list = Ext.create('NotesApp.view.NotesListContainer', {id : 'noteList'});
Ext.Viewport.add(list);
.....
//In place where you need to show list
Ext.Viewport.setActiveItem(list);
If you want to animate swiching between views then use animateActiveItem(list, {type: 'slide', direction: 'right'}) instead a setActiveItem.
It's how you can work with Ext.Viewport and any container with card layout. In the real application view can be created in one part of app(in the controller, int the app, in the view) and set as active in other part. In this case you need get link to the list by any way and use it in the setActiveItem.
There are two techniques 1 using setActiveItem and the other using navigation view...
Navigation View
Set Active item method:
var view=Ext.Viewport.add({xtype: 'testlist'});
Ext.Viewport.setActiveItem(view);
view.show(); //This is additionally done to fire showAnimation

Switch views with button

I have two views. The User view has some text and a button. I want to use that button to switch to the second view. But i don't know how this works with sencha touch 2. When i press the button on the "UserView" (which is the first view), then i get the following error:
Uncaught Error: SYNTAX_ERR: DOM Exception 12
This is basically how my code looks right now:
app.js
Ext.Loader.setConfig({ enabled: true });
Ext.setup({
viewport: {
autoMaximize: false
},
onReady: function() {
var app = new Ext.Application({
name: 'AM',
controllers: [
'Main'
]
});
}
});
The Main controller
Ext.define('AM.controller.Main', {
extend: 'Ext.app.Controller',
views : ['User'],
init: function() {
this.getUserView().create();
this.control ({
'#new': {
tap: function() {
alert('aaaa');
}
}
});
}
});
And the two views:
Ext.define('AM.view.User', {
extend: 'Ext.Container',
config: {
fullscreen:true,
items: [{
xtype: 'button',
text: 'New',
id: 'new'
}
],
html: 'Testing<br />'
}
});
2nd view
Ext.define('AM.view.New', {
extend: 'Ext.Container',
config: {
fullscreen: true,
html: 'w00t'
}
});
Here is your application written the way it should be. Here are a few notes about the changes I made:
You should call Ext.application instead of Ext.setup when creating your MVC application.
All root views should be defined inside your app.js.
You no longer need to use this.control() in your controllers. You can simply use the control configuration in the config block.
You should define all views in the views config of Ext.application.
Instead of creating the view in init, do it in launch. This is components should be added into the view.
app/view/User.js
Ext.define('AM.view.User', {
extend: 'Ext.Container',
config: {
items: [
{
xtype: 'button',
text: 'New',
id: 'new'
}
],
html: 'Testing<br />'
}
});
app/view/New.js
Ext.define('AM.view.New', {
extend: 'Ext.Container',
config: {
html: 'w00t'
}
});
app/controller/Main.js
Ext.define('AM.controller.Main', {
extend: 'Ext.app.Controller',
config: {
control: {
'#new': {
// On the tap event, call onNewTap
tap: 'onNewTap'
}
}
},
launch: function() {
// When our controller is launched, create an instance of our User view and add it to the viewport
// which has a card layout
Ext.Viewport.add(Ext.create('AM.view.User'));
},
onNewTap: function() {
// When the user taps on the button, create a new reference of our New view, and set it as the active
// item of Ext.Viewport
Ext.Viewport.setActiveItem(Ext.create('AM.view.New'));
}
});
app.js
Ext.application({
name: 'AM',
// Include the only controller
controllers: ['Main'],
// Include all views
views: ['User', 'New'],
// Give the Ext.Viewport global instance a custom layout and animation
viewport: {
layout: {
type: 'card',
animation: {
type: 'slide',
direction: 'left',
duration: 300
}
}
}
});
I also suggest you checkout the great guides over on the Sencha Touch API Docs, as well as checking out the Sencha Forums as they are very active and are a great source of information.