Why Width changes after setActiveItem? - sencha-touch

I have a MainView with 'card' layout has 2 items : MenuView and TestView. When I setActive for the MenuView, it has width equal to the MainView's width which is 1280. In the next action after tap a button in menuView, I setActive the TestView, but it's width is only 0. Can anyone explain that for me ? And give me a way to set the TestView's width to 1280.
Here is my code in sencha touch 1:
'Ext.regController('MainController',{
'index': function(options){
if (!Test.views.mainView){
Test.views.mainView = new Test.views.MainView();
}
console.log('mainView width: '+ Test.views.mainView.getWidth());
console.log('menuView width: '+ Test.views.menuView.getWidth());
Test.views.mainView.setActiveItem(Test.views.menuView);
},
'start': function(options){
console.log('testView width: '+ Test.views.testView.getWidth());
Test.views.mainView.setActiveItem(Test.views.testView);
}
});
Test.views.MainView = Ext.extend(Ext.Panel, {
fullscreen : 'true',
layout : 'card',
cardSwitchAnimation : 'slide',
initComponent : function (){
Ext.apply(Test.views, {
menuView: new Test.views.MenuView(),
testView: new Test.views.TestView()
});
this.items = [Test.views.menuView, Test.views.testView]
Test.views.MainView.superclass.initComponent.call(this);
}
});
Test.views.MenuView = Ext.extend(Ext.Panel,{
initComponent: function(){
this.startButton = new Ext.Button({
text: 'Start',
ui: 'action',
scope: this,
handler: function(){
Ext.dispatch({
controller: Test.controllers.mainController,
action: 'start'
});
}
});
this.exitButton = new Ext.Button({
text: 'Exit',
ui: 'action',
scope: this,
handler: function(){
}
});
this.items = [this.startButton, this.exitButton]
Test.views.MenuView.superclass.initComponent.call(this);
}
});
Test.views.TestView = Ext.extend(Ext.Panel,{
initComponent: function(){
this.html = 'test';
Test.views.TestView.superclass.initComponent.call(this);
}
});

You can set width with setWidth();
Test.views.testView.setWidth('50px');

Related

Passing rowIndex to a window in extjs 4

I have a store, a grid, a window and a few text boxes in the window. What I need is that on clicking the actioncolumn in the grid, i need to get the rowIndex of the clicked row and pass it to the window as a parameter. There, i need to load the store and get the values and set it in the appropriate textboxes. I'm not sure how to pass the rowIndex from grid to window on click. Wen I try to alert the value of a in the testfunction, it comes up as undefined. Pls help and below is my code.
Js File:
Ext.onReady(function() {
var rIx;
Ext.create('Ext.data.Store', {
storeId:'employeeStore',
fields:['firstname', 'lastname', 'senority', 'dep', 'hired'],
data:[
{firstname:"Michael", lastname:"Scott", senority:7, dep:"Manangement", hired:"01/10/2004"},
{firstname:"Dwight", lastname:"Schrute", senority:2, dep:"Sales", hired:"04/01/2004"},
{firstname:"Jim", lastname:"Halpert", senority:3, dep:"Sales", hired:"02/22/2006"},
{firstname:"Kevin", lastname:"Malone", senority:4, dep:"Accounting", hired:"06/10/2007"},
{firstname:"Angela", lastname:"Martin", senority:5, dep:"Accounting", hired:"10/21/2008"}
]
});
Ext.create('Ext.grid.Panel', {
title: 'Employee Data',
store: Ext.data.StoreManager.lookup('employeeStore'),
columns: [
{ text: 'First Name', dataIndex: 'firstname' },
{
header: 'Button',
xtype: 'actioncolumn',
icon : 'test.png',
handler: function(grid, rowIndex, colIndex, item, e , record) {
rIx=rowIndex;
//var rec = grid.getStore().getAt(rowIndex);
//alert("Edit " + rec.get('firstname'));
Ext.create('MyWindow').show();
}
}
],
width: 500,
renderTo: Ext.getBody()
});
var testFunction = function(a){alert("a= "+a);
var r = Ext.data.StoreManager.lookup('employeeStore').getAt(a);
var firstname = r.get('firstname');
Ext.getCmp('fname').setValue(firstname);
};
Ext.define('MyWindow', {
extend: 'Ext.window.Window',
store : Ext.data.StoreManager.lookup('employeeStore'),
height: 250,
width: 250,
title: 'My Window',
items: [
{
xtype: 'textfield',
id : 'fname',
fieldLabel:'Name'
}
],
listeners: {
afterrender: Ext.Function.pass(testFunction, [rIx])
}
});
});
Ext.Function.pass(testFunction, [rIx]) takes the current value of rIx when pass is executed. The method is being called long before rIx is ever set to anything meaningful. Javascript is a pass-by-value language. It doesn't matter that eventually rIx gets set to the row index. By that point Ext.Function.pass has already been executed and the parameter it passed in was undefined.
Another approach is to just push the rowIndex onto your window as a property.
Ext.create('Ext.grid.Panel', {
title: 'Employee Data',
store: Ext.data.StoreManager.lookup('employeeStore'),
columns: [
{ text: 'First Name', dataIndex: 'firstname' },
{
header: 'Button',
xtype: 'actioncolumn',
icon : 'test.png',
handler: function(grid, rowIndex, colIndex, item, e , record) {
Ext.create('MyWindow', {rIx: rowIndex}).show();
}
}
],
width: 500,
renderTo: Ext.getBody()
});
Ext.define('MyWindow', {
extend: 'Ext.window.Window',
store : Ext.data.StoreManager.lookup('employeeStore'),
height: 250,
width: 250,
title: 'My Window',
items: [
{
xtype: 'textfield',
id : 'fname',
fieldLabel:'Name'
}
],
listeners: {
afterrender: function(win){
alert("idx= " + win.rIx);
var r = Ext.data.StoreManager.lookup('employeeStore').getAt(win.rIx);
var firstname = r.get('firstname');
Ext.getCmp('fname').setValue(firstname);
}
}
});
Another option is to setup the window's afterrender listener in your handler function instead of adding it in the window's class definition. This approach is a bit cleaner in my opinion. I'm not a big fan of adding unrelated state properties to components.
Ext.create('Ext.grid.Panel', {
title: 'Employee Data',
store: Ext.data.StoreManager.lookup('employeeStore'),
columns: [
{ text: 'First Name', dataIndex: 'firstname' },
{
header: 'Button',
xtype: 'actioncolumn',
icon : 'test.png',
handler: function(grid, rowIndex, colIndex, item, e , record) {
var win = Ext.create('MyWindow');
// add the listener after to avoid bashing any listener config
// that may already exist for the window.
win.on('afterrender', function() {
// rowIndex is available in the closure
alert("idx= " + rowIndex);
var r = Ext.data.StoreManager.lookup('employeeStore').getAt(rowIndex);
var firstname = r.get('firstname');
Ext.getCmp('fname').setValue(firstname);
});
win.show();
}
}
],
width: 500,
renderTo: Ext.getBody()
});

How can I add items to a carousel component from a store load-callback function?

I don't know how to add items in the last two lines of code below. Images from flickr are loading correctly. TR.view.photoset.Carousel.add(items) resulted the error message
"Uncaught TypeError: Object function () { return this.constructor.apply(this, arguments); } has no method 'add' "
Ext.define('TR.view.photoset.Carousel', {
extend: 'Ext.carousel.Carousel',
alias: 'widget.photosetcarousel',
config: {
store: 'PhotosetPhotos',
itemTpl: '<img src="http://src.sencha.io/{[Ext.Viewport.getOrientation()]}/{photo_url}" />',
title: 'Flickr Photoset',
iconCls: 'hot',
iconMask: true,
scrollable: {
direction: 'vertical',
directionLock: true
},
},
initialize: function( me ) {
var store = Ext.getStore('PhotosetPhotos');
store.clearFilter(true);
store.filter('photoset', '72157632230262446' );
store.load();
store.load( function(pictures , operation ) {
var items = [];
Ext.each(pictures, function(picture) {
if (!picture.get('photo_url')) {
return;
}
items.push({
xtype: 'flickrimage',
picture: picture
});
});
// fill items into carousel above
{???}.add(items);
{???}.setActiveItem(0);
});
}
});
Thanks for help ...
I put the code to fill the items in the carousel into the main controller.
Ext.define('MY.controller.Main' , {
extend: 'Ext.app.Controller',
// define a reference to the mycarousel view
refs: [
{
ref: 'mycarouselView',
selector: '#mycarousel'
}
],
// let the control call the init function of the carousel
init: function() {
this.control( {
'#mycarousel': {
initialize: 'initMycarousel'
}
});
},
// then I can access the carousel view and fill it ...
initMycarousel: function() {
var carousel = this.getMycarouselView();
var store = Ext.getStore('MycarouselPhotos');
store.clearFilter(true);
store.filter('photoset', '72157631990018061' );
store.load();
store.load( function(pictures , operation ) {
var items = [];
Ext.each(pictures, function(picture) {
if (!picture.get('photo_url')) {
return;
}
items.push({
xtype: 'image',
src: picture.data.photo_url
});
});
// fill items into carousel
carousel.setItems(items);
carousel.setActiveItem(0);
});
}
Have you tried this instead?
photosetcarousel.setItems(items);
Or maybe give the carousel an id of photosetcarousel, then try:
var photosetcarousel = Ext.getCmp('photosetcarousel');
photosetcarousel.setItems(items);
Not tested...
You can also refer to his example:
http://web.archive.org/web/20121109164506/http://edspencer.net/2012/02/building-a-data-driven-image-carousel-with-sencha-touch-2.html

Extjs 4 MVC custom parameter to store load listener

Inside my Controller i have function that runs after user clicks on item, which loads a store and creates/populates TabPanel with DataView (it works). When user clicks on only one specified item (if clause) i want to split store and create 2 panels with 2 DataViews. How can i pass custom parameter (record.data.name) to store listener so i could check which item was clicked? Or maybe there is different method to achieve what i want? Here is code of my Controller:
init: function() {
this.control({
'gallery_menu': {
itemclick: this.show_gallery
}
});
},
imageStoreLoaded: function(ImageStore, store1, store2) {
},
show_gallery: function(view, record, item, index, e, opts) {
Ext.getCmp('hania-viewport').setLoading('Loading data...');
var tabb = Ext.ComponentQuery.query('.gallery_panel');
var ImageStore = Ext.create('Gallery.store.Images');
ImageStore.load({url: 'myphoto/index.php/api/feed/json/' + record.data.uuid});
var gallery_view;
if (record.data.name == 'Specified_item1') {
var store1 = Ext.create('Gallery.store.Images');
var store2 = Ext.create('Gallery.store.Images');
//THIS WONT WORK - STORE IS NOT LOADED YET;
ImageStore.each(function(r) {
if (r.data.name.substring(0, 2) == 'PS') {
console.log('PS');
store1.add(r.copy());
}else{
console.log('NOT PS');
store2.add(r.copy());
}
});
//IF I ADD LISTENER HOW CAN I RETURN/REFERENCE store1, store2 ???
//OR how can i pass record.data.name so i could check which item was clicked?
ImageStore.addListener('load',this.imageStoreLoaded, this);
var panel1 = Ext.widget('gallery_view', {
title: 'xxx',
autoScroll: true,
store: store1,
flex: 1
});
var panel2 = Ext.widget('gallery_view', {
title: 'yyy',
autoScroll: true,
store: store2,
flex: 2
});
gallery_view = Ext.create('Ext.panel.Panel',{
id: record.data.uuid,
title: 'abc',
layout: {
type: 'hbox',
pack: 'start',
align: 'stretch'
},
closable: true,
autoScroll: true,
items: [panel1, panel2]
});
}else{
gallery_view = Ext.widget('gallery_view', {
title: record.data.name + ' - Photo Gallery',
id: record.data.uuid,
closable:true,
scrollable:true,
autoScroll: true,
store: ImageStore
});
}
if (tabb[0].down('#' + record.data.uuid)) {
tabb[0].setActiveTab(record.data.uuid);
}else{
tabb[0].add(gallery_view);
tabb[0].setActiveTab(gallery_view);
};
}
And the code:
show_gallery: function(view, record, item, index, e, opts) {
Ext.getCmp('hania-viewport').setLoading('Loading data...');
var tabb = Ext.ComponentQuery.query('.gallery_panel');
var ImageStore = Ext.create('Gallery.store.Images');
ImageStore.load({url: 'myphoto/index.php/api/feed/json/' + record.data.uuid});
var gallery_view;
if (record.data.name == 'Do kogo jestem podobna?') {
var store1 = Ext.create('Gallery.store.Images');
var store2 = Ext.create('Gallery.store.Images');
function doStuff() {
console.log(ImageStore);
ImageStore.each(function(r) {
if (r.data.raw_name.substring(0, 2) == 'PS') {
console.log('PS');
store1.add(r.copy());
}else{
console.log('NOT PS');
store2.add(r.copy());
}
});
console.log(store1);
console.log(store2);
}
ImageStore.addListener('load',doStuff, this);
var view1 = Ext.widget('gallery_view', {
title: 'xxx',
store: store1,
flex: 1
});
var panel1 = Ext.create('Ext.panel.Panel',{
title: 'Tata',
items: view1,
flex: 1
});
var view2 = Ext.widget('gallery_view', {
//autoScroll: true,
store: store2,
flex: 1
});
var panel2 = Ext.create('Ext.panel.Panel',{
title: 'Mama',
items: view2,
flex: 1
});
gallery_view = Ext.create('Ext.panel.Panel',{
id: record.data.uuid,
title: 'Do kogo jestem podobna?',
width: 800,
bodyStyle: 'padding: 25px;',
layout: {
type: 'hbox',
pack: 'start',
align: 'stretch'
},
closable: true,
autoScroll: true,
items: [panel1, panel2]
});
}else{
gallery_view = Ext.widget('gallery_view', {
title: record.data.name + ' - Photo Gallery',
id: record.data.uuid,
closable:true,
scrollable:true,
autoScroll: true,
store: ImageStore
});
}
if (tabb[0].down('#' + record.data.uuid)) {
tabb[0].setActiveTab(record.data.uuid);
}else{
tabb[0].add(gallery_view);
tabb[0].setActiveTab(gallery_view);
};
}

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'

tap event not working in view

Please check the code below, what I am doing wrong? I want to output to console when tap event on body.
Ext.define('iApp.view.LoginView', {
extend: 'Ext.Panel',
xtype: 'loginViewPanel',
config: {
style: "background-color: #3f3f3f;",
html: 'hello world',
listeners: {
el: {
tap: function() {
console.log('tapped');
}
}
}
}
});
no output to console...
You are using an old version of adding an element listener.
If you use the compat version fo Sencha Touch 2, it should give you a warning in the console like this:
So your code should look something like this:
Ext.define('iApp.view.LoginView', {
extend: 'Ext.Panel',
xtype: 'loginViewPanel',
config: {
style: "background-color: #3f3f3f;",
html: 'hello world',
listeners: {
tap: {
element: 'element',
fn: function() {
console.log('tapped');
}
}
}
}
});
You can find out more information about the changes on the Sencha Forums.
Update
If you want to delegate to a child of the item, you must still target element, and then within your function check if the tapped element is the one you want:
var component = Ext.Viewport.add({
width: 300,
height: 300,
style: 'background: red',
html: 'Tap me<div id="test" style="background:blue;">Only this will alert</div>',
listeners: {
tap: {
element: 'element',
fn: function(e) {
var element = Ext.get(e.target);
if (element.id == "test") {
alert('tap!');
}
}
}
}
});
If you want to select an element by class or id, it's cleaner to use the delegate option:
var component = Ext.Viewport.add({
width: 300,
height: 300,
style: 'background: red',
html: 'Tap me<div id="test" style="background:blue;">Only this will alert</div>',
listeners: {
tap: {
element: 'element',
delegate: '#test',
fn: function(e) {
alert('Element with id "test" was tapped!');
}
}
}
});
Ext.define('app.view.Card', {
config : {
layout : 'card',
items : [{
xtype : 'panel',
docked : 'top',
html : "<img width='320px' id='image1' src='images/im.jpg'/>",
listeners : {
touchstart : {
element : 'element',
fn : function() {
console.log('tapped')
}
}
}
}]
},
initialize : function() {
// if recording/handling the event in the controller.
this.relayEvents(this.element, ['tap']);
}
});
A simpler and cleaner way of getting Tappable Panels
Ext.define('My.component.TappablePanel', {
extend: 'Ext.Panel',
initialize: function () {
this.element.on('tap', function(){
this.tap();
}, this);
},
tap: function() {
console.log('I heard the tap!');
}
});
And it can be overridden in child classes like so...
Ext.define('My.view.TestPanel', {
extend: 'My.component.TappablePanel',
config: {
html: 'Tap this panel',
style: 'background-color: #5E99CC'
},
tap: function() {
console.log('I handled the tap');
}
});