Stack toolbars and tabpanels in Sencha Touch - sencha-touch

I'm practicing with Sencha Touch. I created a simple tabbar that's docked at the bottom of the screen. Here's my code:
Ext.setup({
tabletStartupScreen: 'tablet_startup.png',
phoneStartupScreen: 'phone_startup.png',
icon: 'icon.png',
glossOnIcon: false,
onReady: function() {
Ext.regModel('ListItem', {
fields: [{name: 'text', type: 'string'}]
});
var d1 = new Ext.data.TreeStore({
model: 'ListItem',
root:{text:'D1',items:{}},
proxy: {
type: 'ajax',
reader: {
type: 'tree',
root: 'items'
}
}
});
var d2 = new Ext.data.TreeStore({
model: 'ListItem',
root:{text:'D2',items:{}},
proxy: {
type: 'ajax',
reader: {
type: 'tree',
root: 'items'
}
}
});
tabBar = new Ext.TabPanel({
id:'tabPanel',
fullscreen:true,
tabBar: {
dock: 'bottom'
},
items:[
new Ext.NestedList({dock:'left',title:'title',iconCls:'home', width:'350', store:d1}),
new Ext.NestedList({dock:'left',title:'title',iconCls:'home', width:'350', store:d2})
]
});
}
});
What I want to do next is create a toolbar directly on top of the tab bar. This toolbar will print some text (which I'll eventually use to create a scrolling newsfeed). How do I add a toolbar directly on top of the tab bar?

Here you go :
tabBar = new Ext.TabPanel({
id:'tabPanel',
fullscreen:true,
tabBar: {
dock: 'bottom'
},
items:[
new Ext.NestedList({
dock:'left',
title:'title',
iconCls:'home',
width:'350',
store:d1,
dockedItems: [{
xtype: 'toolbar',
dock: 'bottom',
items: [{
text: 'Docked to the bottom'
}]
}]
}),
new Ext.NestedList({dock:'left',title:'title',iconCls:'home', width:'350', store:d2})
]
});
The first tab now have a toolbar just above the tabbar

I'm playing around with something similar tonight, trying to add a message bar above the tab bar. I found a nice way to do it using the initComponent method (I'm using lazy instantiation and Ext.extend to create xtypes). Here's a modified version of your tabBar code that worked for me:
tabBar = new Ext.TabPanel({
id:'tabPanel',
fullscreen:true,
tabBar: {
dock: 'bottom'
},
items:[
new Ext.NestedList({dock:'left',title:'title',iconCls:'home', width:'350', store:d1}),
new Ext.NestedList({dock:'left',title:'title',iconCls:'home', width:'350', store:d2})
]
listeners: {
beforerender: function(){
this.addDocked({
html: 'hello world',
dock: 'bottom'
});
}
}
});

Related

Panel not hiding properly

I have a panel whose items are a list and a panel like below
When I click on a button, I want to hide this panel. So far, I managed to do that, but this is what I get
I would like to know how to remove this grey space form the bottom of the panel.
I already this but it's not working :
this.toolsPnl.hide({type:'slide', direction:'up'});
this.doComponentLayout();
this.doLayout();
Update : Code
this.pasteBtn = new Ext.Button({
cls:'paste-copy-tools-panel',
text: 'Coller',
ui: 'normal',
handler : this.onPasteBtnTap,
scope:this
});
this.cancelBtn = new Ext.Button({
cls:'cancel-copy-tools-panel',
text: 'Annuler',
ui: 'normal',
handler: this.onCancelBtnTap,
scope:this
});
this.toolsPnl = new Ext.Panel({
layout:{type:'hbox', align:'stretch'},
height:40,
cls:'document-tools-panel',
hidden:true,
items:[this.pasteBtn,this.cancelBtn]
});
this.currentFolderPnl = new Ext.Panel({
cls:'document-current-folder-panel',
html:'/'
});
this.list = new Ext.List({
flex:1,
cls:'document-list',
id: 'document-list',
store: app.stores.Document,
itemTpl: app.templates.document
});
app.views.DocumentList.superclass.constructor.call(this, {
selectedCls : "x-item-selected",
dockedItems: [{
xtype: 'toolbar',
ui:'dark',
title: 'Documents',
items:[this.backBtn,{xtype:'spacer'},this.newBtn]
}],
layout: 'vbox',
items: [
this.currentFolderPnl,
this.list,
this.toolsPnl,
]
});
May help you with some hack. The main trick is in fixListHeight function, but for showing tools panel for the first time I have to call doComponentLayout for its container first. Don't know why this functionality doesn't work out of the box... have the feeling there is something I have missed. Nevertheless, here is the code.
new Ext.Application({
launch: function() {
// helper property
// indicates whether toolsPnl was shown already
this.first = true;
this.viewport = new Ext.TabPanel({
fullscreen: true,
layout: 'card',
dockedItems: [{
xtype: 'toolbar',
dock: 'top',
items: [{
xtype: 'spacer'
}, {
text: 'show',
listeners: {
tap: function (btn) {
var panel = Ext.getCmp('toolsPnl');
if (panel.isHidden()) {
panel.show({type:'slide', direction:'up'});
btn.setText('hide');
} else {
panel.hide({type:'slide', direction:'up'});
btn.setText('show');
this.fixListHeight();
}
},
scope: this
}
}]
}],
tabBar: {
layout: {
type: 'fit'
}
},
tabBarDock: 'bottom',
items: [{
title: 'Some tabs here...',
id: 'docTab',
iconCls: 'favorites',
layout: 'card',
dockedItems: [{
id: 'toolsPnl',
dock: 'bottom',
html: 'Tools panel',
style: {
'background-color': 'lightblue',
'line-height': '2em',
'text-align': 'center',
'height': '40px',
'width': '100%'
},
hidden:true,
listeners: {
show: function () {
if (this.first) {
Ext.getCmp('docTab').doComponentLayout();
this.fixListHeight();
this.first = false;
}
Ext.defer(function () {
this.fixListHeight(-1);
}, 250, this);
},
scope: this
}
}],
items : [{
xtype: 'list',
id: 'docList',
itemTpl: '{item}',
store: new Ext.data.Store({
data: [{item: 'Some data in the list...'}],
fields: ['item']
})
}]
}]
});
this.fixListHeight = function (direction) {
var panel = Ext.getCmp('toolsPnl'),
tab = Ext.getCmp('docTab'),
list = Ext.getCmp('docList'),
el,
h = list.getHeight(),
dh = panel.getHeight(),
dir = direction || 1;
el = tab.getEl().child('.x-panel-body');
el.setHeight(h + dh * dir);
el.child('.x-list').setHeight(h + dh * dir);
el.down('.x-scroller').setHeight(h + dh * dir);
};
}
});
That looks like the default sencha touch grey. A simple work around would be adding the code below to the panel
style:'background-color:White'

how to slide from a generic home page to nestedlist layout in sencha touch

I'm starting to use sencha touch. I've been able to create a nestedlist layout where clicking on a leaf element triggers a getdetailcard. Now I want to do something that's kind of the reverse of that.
I want to now create a home page with nothing on it but a logo. WHen user clicks on logo, the layout scrolls to a nested list of items.
can someone point me to the relevant documentation or show me sample code?
Thanks
You need to add panel card to your viewport and then on logo tap change the active item.
Here is sample code:
var data = {
text: 'Groceries',
items: [{
text: 'Drinks',
items: [{
text: 'Water',
items: [{
text: 'Sparkling',
leaf: true
}]
}]
}]
};
Ext.regModel('ListItem', {
fields: [{name: 'text', type: 'string'}]
});
var store = new Ext.data.TreeStore({
model: 'ListItem',
root: data,
proxy: {
type: 'ajax',
reader: {
type: 'tree',
root: 'items'
}
}
});
var nestedList = new Ext.NestedList({
title: 'Groceries',
displayField: 'text',
store: store
});
var MyApp = new Ext.Application({
name: 'MyApp',
launch: function() {
MyApp.views.viewport = new Ext.Panel({
fullscreen: true,
layout: 'card',
cardAnimation: 'slide',
items: [
{
xtype: 'panel',
html:'<img src="https://www.google.com/intl/en_com/images/srpr/logo3w.png">',
listeners:{
el:{tap:function(){MyApp.views.viewport.setActiveItem(1,{type:'slide',direction:'left'});}}
}
},
nestedList
]
});
}
});

Sencha Touch Splitview NestedList and getDetailCard

I've seen quite a few examples of a sencha touch app with a nestedList that creates a view within the getDetailCard method and all of that works fine. BUT I have not seen this implemented in an MVC setup. More specifically, a splitview MVC app where the nestedList is docked to the left and the detail pane to the right.
I can use setActiveItem to display a fullscreen detail view with the relevant data all day but when doing so, the left docked nestedlist is removed. How do I keep the split-view setup and update the detailView?
Controller: Products.js
/**
* #class Products
* #extends Ext.Controller
*/
Ext.regController('Products', {
// index action
index: function(){
if ( ! this.indexView){
this.indexView = this.render({
xtype: 'ProductIndex',
});
}
this.application.viewport.setActiveItem(this.indexView);
},
detail: function(options){
var record = options.params[0].attributes.record.data;
console.log(record);
if ( ! this.detailView){
this.detailView = this.render({
xtype: 'ProductDetail',
//data: record
});
//var detailsView = this.indexView.query('#detailsView')[0];
this.detailView.update(record);
}
//this.application.viewport.setActiveItem(this.detailView, options.animation);
}
});
Model: Product.js
Ext.regModel('Product', {
fields: [
{name: "id", type: "int"},
{name: "pid", type: "int"},
{name: "type", type: "string"},
{name: "status", type: "string"},
{name: "title", type: "string"},
{name: "content", type: "auto"},
{name: "date", type: "string"},
{name: "modified", type: "string"}
]
});
MVCApp.ProductStore = new Ext.data.TreeStore({
model: 'Product',
autoLoad: true,
storeId: 'ProductStore',
proxy: {
type: 'ajax',
id: 'ProductStore',
url: 'data/nestedProducts.json',
reader: {
type: 'tree',
root: 'items'
}
}
});
View: ProductIndexView.js
KCI.views.ProductIndex = Ext.extend(Ext.Panel, {
layout: 'hbox',
dockedItems: [
{
dock: 'left',
xtype: 'nestedlist',
width: '320',
height: '100%',
store: 'ProductStore',
displayField: 'title',
useToolbar: Ext.is.Phone ? false : true,
getDetailCard : function(record, parentRecord){
Ext.dispatch({
controller : 'Products',
action : 'detail',
historyUrl : 'Products/index',
params : [record, parentRecord]
});
}
}
],
items: [
{
xtype: 'ProductDetail',
itemId: 'detailView',
width: "704",
height: '100%'
}
]
});
Ext.reg('ProductIndex', KCI.views.ProductIndex);
View: ProductDetailView.js
KCI.views.ProductDetail = Ext.extend(Ext.Panel, {
scroll: 'vertical',
styleHtmlContent: true,
background: '#464646',
html: '<h1>Product Detail</h1>',
tpl: ['{title}<br />{id}<br />{pid}<br />{leaf}<br />{date}<br />{modified}<br />{type}<br />{status}<div>{content}</div>']
});
Ext.reg('ProductDetail', KCI.views.ProductDetail);
Try creating a sub viewport which will contain detail pane. Then you can just setActiveItem for that viewport instead of the application viewport.
I have the answer, this will slide the detail card out, update it and slide it back in.
In my Products controller, I needed to alter my detail view:
detail: function(options)
{
this.currentItem = options.params[0].attributes.record.data;
var rightPanel = this.application.viewport.query('#rightPanel')[0];
if ( ! this.detailView)
{
this.detailView = this.indexView.query('#detailView')[0];
this.dummyView = this.indexView.query('#dummyView')[0];
this.dummyView.on('activate', function()
{
this.detailView.update(this.currentItem);
rightPanel.setActiveItem(this.detailView, {type: 'slide'});
}, this);
}
rightPanel.setActiveItem(this.dummyView, {type: 'slide', reverse: true});
}
Then in my Product Index view, create a sub panel and a dummyview:
var rightPanel = new Ext.Panel({
layout: 'card',
xtype: 'rightPanel',
itemId: 'rightPanel',
items: [
{
xtype: 'ProductDetail',
itemId: 'detailView',
width: "704",
height: '100%',
html: 'right panel'
},
{
itemId: 'dummyView'
}
]
});
EDIT: Wanted to reference my source, and highly talented ST dev: CAM

sencha touch change toolbar with Ext.Carousel

i have a carousel with 3 items and i have 1 toolbar. But how can i change the title of the toolbar depending on which item the carousel is showing? for example:
var theCarousel = new Ext.Carousel({
ui: 'dark',
direction: 'horizontal',
defaults: { cls: 'card', layout:'fit' },
items: [
{
html:'<b>I'm big</b>'
},
{
html:'<i>I'm oblique</i>'
},
{
html:'<u>I'm underlined</u>'
}
});
var toolbar = new Ext.Toolbar({
title: 'iToolbar' ,
dock: 'top',
items:[
{
text:'back',
ui:'back'
},{xtype: 'spacer'},
{
text:'Help',
ui:'help'
}
]
});
var panel = new Ext.Panel({
fullscreen: true,
layout: {
type : 'fit',
align: 'top'
},
defaults: {
flex: 1
},
items: [ theCarousel ],
dockedItems: [ toolbar ]
});
panel.show();
so when i am at the item 'I'm oblique' i want the title of the toolbar to show 'I'm oblique'
Anny ideas on how to do this? Ty, Already!
When each new card is revealed, Ext.Carousel fires an cardSwitch event. The handler of this event will receive the new card component as the second parameter. You can do
panel.setTitle(newCard.getYourTitle());
in the handler.

Sencha touch setActiveItem logic explanation

(complete re-edit of my previous post)
I'm trying to build my first Sencha touch app and i've got a problem.
In my viewport I have 2 xtype : Home and ContainerListAdress.
When I click on the ContainerListAdress icon the card slides to the list.
here is my code (in listcard.js):
// My List view card
myAPP.views.ListAdressCard = Ext.extend(Ext.List, {
id:'listadresscard',
styleHtmlContent: true,
// cardSwitchAnimation: 'slide',
// items: [{ xtype: 'detailcard' } ],
store: myAPP.ListStore,
itemTpl: '<div>{name}</div>',
grouped: true,
onItemDisclosure: function(){
myAPP.views.containerlistadresscard.setActiveItem('detailcard');
}
});
// My container for both the list and the detail view
myAPP.views.ContainerListAdressCard = Ext.extend(Ext.Panel, {
id: "containerlistadresscard",
iconCls: "search",
styleHtmlContent: true,
cardSwitchAnimation: 'slide',
layout:'card',
items: [{xtype:'listadresscard'}, {xtype:'detailcard'}]
});
Ext.reg('listadresscard', myAPP.views.ListAdressCard);
Ext.reg('containerlistadresscard', myAPP.views.ContainerListAdressCard);
Then in detailcard.js I have
DetailcardToolbar = new Ext.Toolbar ({
id:'detailbar',
title: 'station',
dock:'top'
});
myAPP.views.Detailcard = Ext.extend(Ext.Panel, {
id: 'detailcard',
styleHtmlContent: true,
html: 'Made from coffee',
dockedItem:[DetailcardToolbar]
});
Ext.reg('detailcard', myAPP.views.Detailcard);
My error is
Uncaught TypeError: Cannot call method 'setActiveItem' of undefined
If I camelcased containerlistadresscard I got
Uncaught TypeError: Object function (){h.apply(this,arguments)} has no method 'setActiveItem'
But the detailcard I want to set active is referenced in the container ?
Thanks for your help.
---------------------------EDIT----------------------------
I decided to put all in one page, just for clarity, but face the same issue
var myAPPDetailcard = new Ext.Panel ({
id: 'detailcard',
styleHtmlContent: true,
html: 'Made from coffee',
layout: 'fit'
});
var myAPPListAdressCard = new Ext.List ({
id:'listadresscard',
styleHtmlContent: true,
store: myAPP.ListStore,
itemTpl: '<div>{name}</div>',
grouped: true,
onItemDisclosure: function(){
myAPP.views.ContainerListAdressCard.setActiveItem(myAPPDetailcard);
}
});
// My container for both the list and the detail view
myAPP.views.ContainerListAdressCard = Ext.extend(Ext.Panel, {
id: "containerlistadresscard",
iconCls: "search",
styleHtmlContent: true,
cardSwitchAnimation: 'slide',
layout:'card',
items: [myAPPListAdressCard, myAPPDetailcard]
});
Ext.reg('containerlistadresscard', myAPP.views.ContainerListAdressCard);
No, Ext.extend() defines a class. Here you created a class this way:
myAPP.views.ContainerListAdressCard = Ext.extend(Ext.Panel, {
id: "containerlistadresscard",
iconCls: "search",
styleHtmlContent: true,
cardSwitchAnimation: 'slide',
layout:'card',
items: [myAPPListAdressCard, myAPPDetailcard]
});
Then you create an instance of it like this way:
var mainContainer = new myAPP.views.ContainerListAdressCard({
fullscreen : true
});
You can call setActiveItem() on this mainContainer variable, not on a class definition.
.....
onItemDisclosure: function(){
mainContainer.setActiveItem(myAPPDetailcard);
}
Hope this help.