PDA

View Full Version : Show and Hide Docked Items.



irfaniqbal
21 Jan 2011, 7:19 AM
Hi,
I have a panel with Top and Bottom docked items and these docked items are initially Hidden. I want to show these docked items by Clicking a button. How can i achieve this.



var dockedItems = [
{
xtype: 'toolbar',
ui: 'light',
dock: 'bottom',
items: buttonsSpecBottom,
hidden: true
},
{
xtype: 'toolbar',
ui: 'light',
dock: 'top',
items: [buttonsSpecTop,{xtype: 'spacer'}, buttonsSpecHome],
hidden: true
}
];


Application.App = Ext.extend(Ext.Panel, {
fullscreen: true,
layout: 'card',
activeItem: 0,
dockedItems: dockedItems ,
initComponent: function() {
this.startScreen = new Application.views.login({
flex: 1
});
this.homeScreen = new Application.views.home();
this.supplementsScreen = new Application.views.supplements();
this.nutritionScreen = new Application.views.nutrition();

this.items = [this.startScreen, this.homeScreen,this.nutritionScreen,this.supplementsScreen];

Application.App.superclass.initComponent.call(this);

}
});
thanks in advance.

AndreaCammarata
21 Jan 2011, 8:38 AM
Hi infaniqbal.
Let's start to set an id to your toolbars:



var dockedItems = [
{
xtype: 'toolbar',
id: 'toolbar1',
ui: 'light',
dock: 'bottom',
items: buttonsSpecBottom,
hidden: true
},
{
xtype: 'toolbar',
id: 'toolbar2',
ui: 'light',
dock: 'top',
items: [buttonsSpecTop,{xtype: 'spacer'}, buttonsSpecHome],
hidden: true
}
];
Then when you have to show them simply write



Ext.getCmp('toolbar1').setVisible(true);
Ext.getCmp('toolbar2').setVisible(true);
Hope this helps.

mitchellsimoens
21 Jan 2011, 8:45 AM
Ugh.... never gonna get over people using getCmp(). ID independent:


var docked = panel.getDockedItems();
docked[0].setVisible(true);

AndreaCammarata
21 Jan 2011, 8:49 AM
Michell I don't like it too, but in big project with multi components getCmp() is the only way.
In this case your solution is good, but I don't like access to component by an index.
Index should change, id may be te same over time.

mitchellsimoens
21 Jan 2011, 8:50 AM
A better way for you:


Application.App = Ext.extend(Ext.Panel, {
fullscreen: true,
layout: 'card',
activeItem: 0,
initComponent: function() {
this.dockedItems = this.buildDocks();

this.items = this.buildItems();

Application.App.superclass.initComponent.call(this);

},
buildItems: function() {
this.startScreen = new Application.views.login({
flex: 1
});
this.homeScreen = new Application.views.home();
this.supplementsScreen = new Application.views.supplements();
this.nutritionScreen = new Application.views.nutrition();
return [
this.startScreen,
this.homeScreen,
this.nutritionScreen,
this.supplementsScreen
];
},
buildDocks: function() {
return [
{
xtype: 'toolbar',
ui: 'light',
dock: 'bottom',
items: buttonsSpecBottom, //redo
hidden: true
},
{
xtype: 'toolbar',
ui: 'light',
dock: 'top',
items: [buttonsSpecTop,{xtype: 'spacer'}, buttonsSpecHome], //redo
hidden: true
}
];
}
});

This is a better application structure. Your toolbar buttons need to be moved inside the App also tho and then you will get the scope of the application.

mitchellsimoens
21 Jan 2011, 8:59 AM
but in big project with multi components getCmp() is the only way.

That is just incorrect to be honest. Create your own references or use ComponentQuery. Using IDs is really bad, structure of components doesn't change that much and is easily fixed. Everything you do should be extensible, dynamic, and reusable. This is why IDs are bad, you cannot reuse them.

AndreaCammarata
21 Jan 2011, 9:15 AM
That is just incorrect to be honest. Create your own references or use ComponentQuery. Using IDs is really bad, structure of components doesn't change that much and is easily fixed. Everything you do should be extensible, dynamic, and reusable. This is why IDs are bad, you cannot reuse them.

Michell sorry but I don't agree with you!
If for example I have to dinamically insert a button into a toobar as the first button just in some conditions, this makes your components index change but id is always the same, so sometimes could be really hard to control all your application by index.
ID are not bad at all, you just have to look out to assign real unique ID.

mitchellsimoens
21 Jan 2011, 9:17 AM
It goes against good OOP practices. Guess we are not going to agree with this so as long as you are ok with it, let's not get into a thread fight :)

AndreaCammarata
21 Jan 2011, 10:42 AM
It goes against good OOP practices. Guess we are not going to agree with this so as long as you are ok with it, let's not get into a thread fight :)
Absolutely...the last thing I want is to go into a thread fight, if you can convince me that using id is bad I'm glad to follow your street ;)
I agree with you when you when you say that everything has to be dynamic and reusable but id don't mess with that and I don't understand why you say it goes against OOP practices.
Remember that Sencha Touch / Ext component are nothing more than div created inside your page, and, as W3C say, every dom node should have an unique id.
So setting the id on you component makes your div created with an unique id.
Yes, it's better don't use too much getCmp() because the ComponentManager should look for the wanted component through all the existing components in your application and this is not really the best, but sometime I think you have no choise.
Obviously if you are creating your custom component extending from an existing Sencha component you should not set id inside the class, but you will asign the id on the new class that you are going to create with type of your custom defined class.
Anyway absolutely no problem Michell, this doesn't want to be a fight but just a way to help all the new Sencha Touch users :)

mitchellsimoens
21 Jan 2011, 10:52 AM
Keeping it light, Sencha will automatically set a unique ID. But when you try to refer to it, how can you get this unique ID.

When I create an App, I don't just add some Panels. Each "screen" is actually just an extension of another component. Then I instantiate that extension when needed. This is reusable.

If a function is used more than once, it is abstracted out and that creates a base for what to extend upon. This is reusable and extensible. Think of how Panel extends Component. Component code is reusable so Panel just extends it.

So say I have an App and it the basis is a Panel. Panel uses CardLayout. Each "card" under it is an extension of an abstract. My secret for performance is to only have 1 or 2 cards rendered at once. I destroy what isn't being viewed and recreate it when needed. This makes all my animations smooth versus others that are choppy (even on the contest winners). So managing all the unique IDs is just not feasible and since I only have 1 card rendered, I can use getActiveItem(). The active card then holds references to the components under it that I need. Keeping with performance, each card doesn't have much on it so managing those references are now simple. I don't create references to everything, just what I need.

So I accomplished 2 things. Never use IDs and unmatched performance.

gcallaghan
21 Jan 2011, 11:00 AM
I am curious about your technique for destroying and creating cards. Could you give a simple example of how you accomplish that?

mitchellsimoens
21 Jan 2011, 11:00 AM
I am curious about your technique for destroying and creating cards. Could you give a simple example of how you accomplish that?

My trade secret? haha let me put together something and I will

AndreaCammarata
21 Jan 2011, 11:41 AM
Keeping it light, Sencha will automatically set a unique ID. But when you try to refer to it, how can you get this unique ID.

You are right Sencha assign unique id to components so what is wrong if I want assign my custom id? I make the same question to you, if you let Sencha assign auto id for all the components how do you refer to them? My reply is simple, assign your custom id.
In the example I post you, if you have to create and insert a button in a dynamic way, how can you access the components by index? All the functions that refer to a button at index 0, after that, should use index 1, an all the other buttons inside the same toolbar shift by 1, so the same for all other buttons. It depends by the situation! As already said, in normal condition, I prefer to don't use getCmp() but sometime this could be a good solution. I think you look too much at ComponentMgr as an evil object :).
So for you, even the ComponentQuery should not be use at all?


When I create an App, I don't just add some Panels. Each "screen" is actually just an extension of another component. Then I instantiate that extension when needed. This is reusable.

If you add a panel, you are just adding a new istance of Panel object with different configurations, you are not extending that object.
To extend an object you use Ext.Extend. Then you can add istances of the new type to your application. This is OOP.
(Maybe I misunterstood and this is what you do? Do you create every panel from a different abstracted class?)



If a function is used more than once, it is abstracted out and that creates a base for what to extend upon.

I don't doubt about it, that's what I do too :)

However the way you use your card layout is interesenting, but I don't doubt neither to the fact that you should destroy items you don't use anymore.

I don't know if you saw some video on the project I 'm working on:
http://www.sencha.com/forum/showthread.php?121563-Real-Time-File-Sharing-iTunes-Files-Sync-%28Aral-CMS%29

This project is composed by around 250 different javascript.
Every one of each include a custom class, the inherith from another class and so on.
The modules are extension of my custom base classes that contains shared functions / components, so, in this way, I can use them even with Ext interface.

mitchellsimoens
21 Jan 2011, 4:35 PM
I am curious about your technique for destroying and creating cards. Could you give a simple example of how you accomplish that?

I was going to write a blog about it but decided it was just too much. I have attached source code to back this up.

So what is going on... I have a Panel that will hold everything. I have a top dock and bottom dock. Top dock holds a title and buttons only related to individual screens. The bottom dock is for the application as a whole like a Menu button or a Home button.

The default screen is just a Component with some static HTML. I tend to just show simple stuff on the default screen like static HTML or an image.

I have 3 Panels called Card1, Card2, and Card3. Card1 holds a List, Card2 gets updated with HTML from a Template, and Card3 is a FormPanel.

So click on the Start button on the bottom dock. This will switch to Card1 and show a List. Nothing is destroyed but the List and Store is NOT added to Card1 until the 'activate' event is fired. This allows the animation to be smooth. So click/tap on an item in the List, this now adds Card2 to the App Panel with the record you tapped on and then sets that new component as the active item. Card1 then fires the 'deactivate' event and destroys itself and it's children. It will also delete any references I have made.

Card2's 'activate' event fires and like Card1 it will then execute it's buildItems function which just updates itself with some HTML fed by the Template which was fed by a record. So right now, you have the default screen and Card2 rendered as Card1 has been destroyed. This also shows two buttons on the top dock: Back and Edit. If you click Back, it will add Card1 back to the App Panel and set it as the active item. If you click Edit, it will add Card3 (a FormPanel) with the record and set it as the active item. Either button you press, it will fire it's 'deactivate' event which I have setup to destroy itself and the record reference.

Say you clicked on Edit, it added Card3 with the record. Once Card3 fires it's 'activate' event and will build it's children, in this case a single Text field. You will also notice that I add a listener for the 'afterlayout' event. I do this because I do not want to execute Card3's loadRecord function before the fields have been laid out or else it won't load the data from the record correctly. You can click Cancel and it will take you back to Card2 with the record.

As a summary, I listen for the 'activate' and 'deactivate' events. The 'activate' listener will build all the items after the animation. The 'deactivate' will destroy everything after the animation. REMEMBER TO DELETE ANY REFERENCES LIKE I DO WITH this.rec! If you do not, you have just created a memory leak. For FormPanels, I listen for the 'afterlayout' event to load the Record I pass through.

So it adds things when needed and removes when not needed. The trick is to make it work with each other like Card3 cannot work properly without getting the Record from Card2 and going from Card3 back to Card2 will not work without repassing the Record to Card2.

Usually I am not the best at describing step-by-step what is going on which is why I have provided the source. I learn best by just reading source. Let me know if you do not understand something.

gcallaghan
21 Jan 2011, 5:19 PM
Thanks Mitchell!

mitchellsimoens
21 Jan 2011, 5:26 PM
Thanks Mitchell!

No problem! I don't want people to keep making apps that are slow and choppy. Everything I do, I think of the impact it will have on performance and then I find out the best way to do it. I want to see some really cool stuff so I will always help peoplenfine tune things. If that means giving away my secrets, as long as I get some credit it is ok.

Post back some stuff that you do if you can!

irfaniqbal
22 Jan 2011, 3:04 AM
Hi infaniqbal.
Let's start to set an id to your toolbars:



var dockedItems = [
{
xtype: 'toolbar',
id: 'toolbar1',
ui: 'light',
dock: 'bottom',
items: buttonsSpecBottom,
hidden: true
},
{
xtype: 'toolbar',
id: 'toolbar2',
ui: 'light',
dock: 'top',
items: [buttonsSpecTop,{xtype: 'spacer'}, buttonsSpecHome],
hidden: true
}
];
Then when you have to show them simply write



Ext.getCmp('toolbar1').setVisible(true);
Ext.getCmp('toolbar2').setVisible(true);
Hope this helps.

Thanks all for contributing your thoughts in this thread.

@Andrea: I have used your code snippet in my app but did not get required result. In my case, i have a login page and Other pages which were included in a Main Panel. and I did not want to show toolbars at Login page that is why i set toolbar's "hidden: true" initially. and as the user authenticate from server i call following function:


var isLoginItem = function(){

Ext.getCmp('toolbar1').setVisible(true);
Ext.getCmp('toolbar2').setVisible(true);

app.doLayout();
app.doComponentLayout();
}
which does not show toolbars properly. i have also attached screen shot that page. Please tell me where i m wrong. thanks in advance.
24414

AndreaCammarata
22 Jan 2011, 3:21 AM
No problem! I don't want people to keep making apps that are slow and choppy. Everything I do, I think of the impact it will have on performance and then I find out the best way to do it. I want to see some really cool stuff so I will always help peoplenfine tune things. If that means giving away my secrets, as long as I get some credit it is ok.

Post back some stuff that you do if you can!

You still have not reply to my post :).
Do you have a solution for my example using your by Index technique? :)



Post back some stuff that you do if you can!


http://www.sencha.com/forum/showthread.php?121563-Real-Time-File-Sharing-iTunes-Files-Sync-%28Aral-CMS%29
I don't think my app is slow at all :D

Cheers

irfaniqbal
22 Jan 2011, 3:46 AM
Its been good to see a cold war between two experts. :D

@andrea: i would like you to respond to my query. thanks

AndreaCammarata
22 Jan 2011, 3:52 AM
Its been good to see a cold war between two experts. :D

@andrea: i would like you to respond to my query. thanks

Hi infaniqbal.
I post you a simple exampe to show you how to show or hide docked items.
The first thing you have do do is create a new javascript named "loginPanel.js" an put this code inside.



Ext.ns('ux');

ux.loginPanel = Ext.extend(Ext.Panel, {

initComponent : function(){

//Creation of the top docked toolbar
this.toolbar1 = new Ext.Toolbar({
dock: 'top',
items: [{
xtype: 'button',
text: 'Show Toobar 2',
listeners: {
tap: function(){
this.toolbar2.setVisible(true);
},
scope: this
}
}]
});

//Creation of the bottom docked toolbar
this.toolbar2 = new Ext.Toolbar({
dock: 'bottom',
items: [{
xtype: 'button',
text: 'Hide Toobar 1',
listeners: {
tap: function(){
this.toolbar1.setVisible(false);
},
scope: this
}
}]
});

//Configuration of the panel dockedItems
this.dockedItems = [this.toolbar1, this.toolbar2];

//Call the superclass initComponent event
ux.loginPanel.superclass.initComponent.call(this);

},

afterRender: function(cmp) {

//Call the superclass afteRender event
ux.loginPanel.superclass.afterRender.call(this, cmp);

//Set toolbar2 invisible
this.toolbar2.setVisible(false);

}

});
Then in your main "index.js" put this code:



Ext.setup({

onReady: function() {

var panel = new ux.loginPanel({
fullscreen: true,
styleHtmlContent: true,
html: 'This is just a simple example'
});

}
});
I will provide some additional information later about this code, someone is waiting for me at launch ;)
(I'm from Italy ;))

PS: This is not a war but just a way to learn something new :D

Bucs
22 Jan 2011, 9:29 AM
No problem! I don't want people to keep making apps that are slow and choppy. Everything I do, I think of the impact it will have on performance and then I find out the best way to do it. I want to see some really cool stuff so I will always help peoplenfine tune things. If that means giving away my secrets, as long as I get some credit it is ok.

Post back some stuff that you do if you can!


Mitchell, your post was awesome btw. Your concern with performance is well founded as I know I am guilty of throwing code together just to get the job done under unrealistic mgmt deadlines (are any realistic? :)). When I first started building Touch apps, I thought that by leaving pages loaded after first use and simply refreshing data on the page if it was called again was going to be "snappier" than a destruction and recreation of the page. Boy was I wrong! Doing so really effects the performance of the app and you can also get caught up in a battle when trying to correctly re-render a page with new data (with things like new image sizes etc)...at least I found it to be a struggle. Once I realize that destroying the page and recreating it added very little overhead to the app, and dramatically simplifies the rendering process..and performance was increased as a result. Anyway, great post and thanks for taking the time to put that together!

I do have a couple questions though. In the following code, you say that the method will be called when the parent panel is destroyed. How does that happen, I don't see any code to make that happen? Did you mean to call this in the destroyItems() method?



cleanUpList: function() {
//will automatically be called when the parent Panel is destroyed
delete this.listStore;
delete this.list;
},



Also, what properties do you call 'delete' on, anything you assign as a property to the current (this) component container? I see now that I was not cleaning up properly on component destruction by removing my references, but I guess I'm trying to figure out exactly what I need to cleanup with delete. In reading, you can only delete assigned properties (because they are not marked with DontDelete attribute), so exactly what should I be looking to delete? Why doesn't destroy() clean up these references for us if they are in fact properties of the object being destroyed?

Lastly, why setup a separate destroyItems() method? Why not just have the deactivate() call this.destroy() then add cleanup code to the OnDestroy event before calling the superclass destroy?

Thanks again for you post, very informing.

mitchellsimoens
22 Jan 2011, 9:37 AM
in App.Card1.js, I have that function cleanUpList. I set a listener to the List component on line 56 of App.Card1.js to listen to the 'beforedestroy' event. When the Panel destroys, it first executes all it's children's destroy methods so therefor when you destroy the Panel, it will destroy the List which in turn executes the 'beforedestroy' event.

Any property that you add, you need to handle the clean up.

For instance, by default the List requires you to set the store property; therefor, the List will automatically clean up that store property. This includes anything in the API Docs under config and public properties (and also any private properties the component creates). So I added this.listStore and this.list to the Panel, which by default isn't a config or public/private property, so I had to write the code to clean that up.

mitchellsimoens
22 Jan 2011, 9:39 AM
You still have not reply to my post :).
Do you have a solution for my example using your by Index technique? :)

If you take a look at my example source, you will see I set references. I also use getComponent(index) to get the buttons because I don't like to add/remove buttons. I feel that App startup can be longer but for sake of usability when the user gets in and starts using it that showing and hiding is a better approach.

Bucs
22 Jan 2011, 9:56 AM
Any property that you add, you need to handle the clean up.
.

That basically sums it up perfectly, thanks. Lastly, I am getting warnings in the debug console any time I am destroying components. The warning is as follows:



Attempted to remove a component that does not exist. Ext.Container: remove takes an argument of the component to remove. cmp.remove() is incorrect usage. sencha-touch.js:6


I do not call "cmp.remove()" anywhere in my code...is this a bug in Touch? Using 1.0.2.

mitchellsimoens
22 Jan 2011, 10:00 AM
Attempted to remove a component that does not exist. Ext.Container: remove takes an argument of the component to remove. cmp.remove() is incorrect usage. sencha-touch.js:6


I do not call "cmp.remove()" anywhere in my code...is this a bug in Touch? Using 1.0.2.

In my example code?

There are two ways to remove a child, you can call the child's destroy method (which is what I like to do, have the child manage itself) or call the parent's remove function with the child as a param.

Bucs
22 Jan 2011, 10:03 AM
Sorry, no...nothing to do with your code. I am seeing this in MY app where I am destroying components upon deactivation. I have no clue where that warning message is coming from...i guess you haven't seen that yet. Trying to figure out if it's something I am doing wrong or if it's a bug in Touch 1.0.2.

mitchellsimoens
22 Jan 2011, 10:10 AM
I haven't seen 1.0.2 yet so I'm not sure.

What I would do is look at what is going on. You know it's destruction based as, well, it's an error with remove. So I would start seeing where in your function that handles destruction is going on. Two ways:

1) I put console.log after I execute anything. Then look at the console and see after which console.log the error happens. I know then which line is failing. Example:


destroyItems: function() {
console.log(1);
this.someFn();
console.log(2);
this.anotherFn();
}

If in the console I see:

1
2
some error here
Then I know that it is the line just after the console.log(2).

2) This is probably the preferred way. You can set breaks in the console code. To do this, in the Console, click on the Scripts tab. Make sure you are in the correct file by using the "drop down" just above the source code. Then navigate to the function in question and click on the line number. This will add a break. Click again and it will remove. You can also right-click on the line numbers to do actions. This will stop the code execution on those breaks. So instead of console.log every other line, you can now set break points till you find out which line is throwing an error.

mitchellsimoens
22 Jan 2011, 10:13 AM
Another thing you can do is try a different version of Sencha Touch. I never delete a folder, I always just add a new release to my folder where I keep all the releases just in case I need to test on an earlier version.

Bucs
22 Jan 2011, 10:28 AM
Yeah, I don't know how you could ever develop these apps without knowing how to use the debugger :)

In any event, I have a listener on the panel beging destroyed like so:


beforedeactivate : function (cmp) {
//alert('destroy will be called on detail component.');
this.destroy();
},


And then do the following in an onDestroy handler:


onDestroy: function(){
Ext.each(this.formItems, function(item){
item.destroy();
});
....ns....superclass.onDestroy.call(this);
},


Using break points on this.destroy() and Ext.each....the warning occurs when the code moves from the this.destroy call to the break on Ext.each...before the each is executed. So, either I am not declaring the onDestroy correctly (do I need a function param?) or this is a bug in 1.0.2.

mitchellsimoens
22 Jan 2011, 10:31 AM
Remember, when a component get's destroyed, it will automatically fire each of it's children component's destroy method.

So I'm thinking the children may already have been destroyed when you (or Sencha Touch) are trying to destroy them.

Also, I'm not too sure the timing of when "beforedeactivate" and "deactivate" is. Beauty of using "deactivate" (IMHO of course) is that it fires *AFTER* the animation, keeping the animation smooth. However, the downside is that you are building items in the new component and destroying in the old component at the same time. Guess you would just have to play with it to see what you like best.

Bucs
22 Jan 2011, 3:40 PM
Yeah, something is definitely not right...may have to post a bug report. If I take your exact code and place as a card in my app which also uses a card layout as the main viewport...I still get the error immediately when the destroy method is called. However, if I take your app and use with version 1.0.2, it does not cause the error on destroy. That leaves the only difference being that my app uses the MVC pattern and yours does not. Not sure why/why/how that would cause my issue, but it's the only difference. Can't be a child issue b/c I'm using the exact same code as you. Stepping into source does nothing for me a it just tells me that an undefined cmp is getting passed in from somewhere during the destroy() method call. Really have not clue at this point and have spent entirely too long on this and it's only a warning message.

mitchellsimoens
22 Jan 2011, 3:42 PM
Oh... wish I had 1.0.2 to help ya

irfaniqbal
24 Jan 2011, 12:08 AM
Hi infaniqbal.
I post you a simple exampe to show you how to show or hide docked items.
The first thing you have do do is create a new javascript named "loginPanel.js" an put this code inside.



Ext.ns('ux');

ux.loginPanel = Ext.extend(Ext.Panel, {

initComponent : function(){

//Creation of the top docked toolbar
this.toolbar1 = new Ext.Toolbar({
dock: 'top',
items: [{
xtype: 'button',
text: 'Show Toobar 2',
listeners: {
tap: function(){
this.toolbar2.setVisible(true);
},
scope: this
}
}]
});

//Creation of the bottom docked toolbar
this.toolbar2 = new Ext.Toolbar({
dock: 'bottom',
items: [{
xtype: 'button',
text: 'Hide Toobar 1',
listeners: {
tap: function(){
this.toolbar1.setVisible(false);
},
scope: this
}
}]
});

//Configuration of the panel dockedItems
this.dockedItems = [this.toolbar1, this.toolbar2];

//Call the superclass initComponent event
ux.loginPanel.superclass.initComponent.call(this);

},

afterRender: function(cmp) {

//Call the superclass afteRender event
ux.loginPanel.superclass.afterRender.call(this, cmp);

//Set toolbar2 invisible
this.toolbar2.setVisible(false);

}

});
Then in your main "index.js" put this code:



Ext.setup({

onReady: function() {

var panel = new ux.loginPanel({
fullscreen: true,
styleHtmlContent: true,
html: 'This is just a simple example'
});

}
});
I will provide some additional information later about this code, someone is waiting for me at launch ;)
(I'm from Italy ;))

PS: This is not a war but just a way to learn something new :D

Thanks Andrea for your reply. But still i have a problem with it.

you have put Docked items in login panel but in my case the scenario is different. In my case Login panel is one of the items of my Apps main Panel and i want to put Docked Items in that Main Panel. so that it will remain same through out my whole application.

I don't think that by applying your code the Docked Items will show on all the other panels of Apps Main Panel. Hope you understand my point. If not, do let me know.

thanks

irfaniqbal
24 Jan 2011, 12:35 AM
Hi Andrea,
I have just solved that problem. But just one more problem now. hope you will not mind it.
The problem is that when i setVisible(false) of docked items on login panel, it hides the docked items. But the space docked Items take remains there (Please see attached image).
24425
thanks

irfaniqbal
24 Jan 2011, 5:57 AM
still waiting for reply :(

AndreaCammarata
24 Jan 2011, 6:05 AM
Hi infaniqbal.
Sorry if I'm slow to reply but I'm very busy at the moment :(.
Anyway I try to do my best to help the community.
Did you try to call a doComponentLayout on your panel after hiding the toolbar?

AndreaCammarata
24 Jan 2011, 6:09 AM
Or try to call



myToolbar.hide()


instead



myToolbar.setVisible(false)

irfaniqbal
24 Jan 2011, 6:11 AM
its ok Andrea. I have tried DoComponentLayout and DoLayout. but nothing happened. Hope to get a solution from you soon. thanks

irfaniqbal
24 Jan 2011, 6:56 AM
the problem remains there :(

AndreaCammarata
24 Jan 2011, 7:53 AM
Hi infaniqbal.
The problem seems to be a Sencha bug, because for how much I tried to force the panel to recalculate the layout, it "doesn't makes a move". The tooolbar white space is always there.
This is caused because the panel body doesn't set it's top style position to 0, but it mantains the same value of when the toolbar was visible.
However I post you a little example that show you a little trick to reset the panel body position in it's correct position after hiding the top toolbar.



Ext.setup({
onReady: function() {
var myPanel = new Ext.Panel({
id: 'mainPanel',
bodyPadding:'0',
margin:'0',
fullscreen: true,
html: '<p>This is a Test</p>',
scroll: true,
dockedItems: [{
xtype: 'toolbar',
id: 'topToolbar',
dock: 'top',
title: 'Hide Me!'
},{
xtype: 'toolbar',
dock: 'bottom',
items: [{
text: 'Hide Top Toolbar',
handler: function(){

//Hiding the top toolbar
myPanel.getDockedComponent('topToolbar').setVisible(false);

//FIX: Reset the panel body top style
myPanel.body.setStyle('top',0);
},
}]
}]
});
}
});
Obviously apply this trick to your code and your issue will be solved until Sencha don't fix this bug.

Hope this helps.

mitchellsimoens
24 Jan 2011, 8:24 AM
myPanel.doComponentLayout()

didn't do the trick @andreacammarata. I did this in the early betas and that fixed it.

AndreaCammarata
24 Jan 2011, 8:27 AM
myPanel.doComponentLayout()didn't do the trick @andreacammarata. I did this in the early betas and that fixed it.

It doesn't work, I already post another solution!
Please mitchell read all the posts before write something, don't write only to do something.

mitchellsimoens
24 Jan 2011, 8:41 AM
It doesn't work, I already post another solution!
Please mitchell read all the posts before write something, don't write only to do something.

Do you know how many posts I help with? Do you know how many projects I work on? Kind of hard to care about something so small so reading all the posts... nah. Only to do something... wow

AndreaCammarata
24 Jan 2011, 8:50 AM
Do you know how many posts I help with? Do you know how many projects I work on? Kind of hard to care about something so small so reading all the posts... nah. Only to do something... wow

Michell noone say you have to reply to all the post. Just do what you are able to do.
You are good, Me and others people thank you to reply to a lot of posts, but in this case if you don't read all the post inside a thread how you can help the community?
C'mon it seems your are in battle, you are losing the main focus to help the community.
If you really want to help, post some example that are easy to read to all the newbies.

PS: Don't worry be happy :)

irfaniqbal
24 Jan 2011, 10:39 AM
thank Andrea for your reply. But this Tweak also does not work. when i setStyle('top', 0), the top position is ok but it creates a margin from bottom. Also Home panel's List move up. Have a look at this screen shot.
24439

irfaniqbal
24 Jan 2011, 10:41 AM
Hi infaniqbal.
The problem seems to be a Sencha bug, because for how much I tried to force the panel to recalculate the layout, it "doesn't makes a move". The tooolbar white space is always there.
This is caused because the panel body doesn't set it's top style position to 0, but it mantains the same value of when the toolbar was visible.
However I post you a little example that show you a little trick to reset the panel body position in it's correct position after hiding the top toolbar.



Ext.setup({
onReady: function() {
var myPanel = new Ext.Panel({
id: 'mainPanel',
bodyPadding:'0',
margin:'0',
fullscreen: true,
html: '<p>This is a Test</p>',
scroll: true,
dockedItems: [{
xtype: 'toolbar',
id: 'topToolbar',
dock: 'top',
title: 'Hide Me!'
},{
xtype: 'toolbar',
dock: 'bottom',
items: [{
text: 'Hide Top Toolbar',
handler: function(){

//Hiding the top toolbar
myPanel.getDockedComponent('topToolbar').setVisible(false);

//FIX: Reset the panel body top style
myPanel.body.setStyle('top',0);
},
}]
}]
});
}
});
Obviously apply this trick to your code and your issue will be solved until Sencha don't fix this bug.

Hope this helps.

thank Andrea for your reply. But this Tweak also does not work. when i setStyle('top', 0), the top position is ok but it creates a margin from bottom. Also Home panel's List move up. Have a look at this screen shot.
24440

AndreaCammarata
24 Jan 2011, 11:10 AM
Try in this way



Ext.setup({
onReady: function() {
var myPanel = new Ext.Panel({
id: 'mainPanel',
bodyPadding:'0',
margin:'0',
fullscreen: true,
html: '<p>This is a Test</p>',
bodyStyle: 'background-color: Blue',
scroll: true,
dockedItems: [{
xtype: 'toolbar',
id: 'topToolbar',
dock: 'top',
title: 'Hide Me!'
},{
xtype: 'toolbar',
dock: 'bottom',
items: [{
text: 'Hide Top Toolbar',
handler: function(){

//Hiding the top toolbar
myPanel.getDockedComponent('topToolbar').setVisible(false);

//FIX: Reset the panel body top style
myPanel.body.setStyle('top',0);
myPanel.doLayout();
},
}]
}],
listeners: {
afterlayout : function(pnl, lay){
pnl.body.setStyle('height', pnl.height + 'px');
}
}
});
}
});


I don't like it very much, but it's the fastest way I found. If someone know how to fix this in a better way, please share ;)

gcallaghan
24 Jan 2011, 12:05 PM
I solved a similar problem by calling removeDocked when hiding and addDocked when showing. There is extra layout code within these methods that calculate the dimensions of the body/content element. This code is only called when adding/removing docked items, not in doComponentLayout.



MyPanel = Ext.extend(Ext.Panel,{
...
listeners:{
...
hidetabbar:function(){
console.log('tabbar hidden');
this.tabBar.hide(false);
this.removeDocked(this.tabBar,false);
this.doComponentLayout();
},
showtabbar:function(){
console.log('tabbar shown');
this.tabBar.show();
this.addDocked(this.tabBar);
this.doComponentLayout();
},
...
initComponent:function(){

var obj = this;
MyPanel.superclass.initComponent.call(obj);
obj.addEvents(
...
'hidetabbar',
'showtabbar',
...
);

obj.tabBar= obj.getDockedComponent(0);
...
}
...
});


to see the sencha code that handles this take a look at: src/platform/src/layout/component/DockLayout.js
The comments are very helpful.

AndreaCammarata
24 Jan 2011, 12:15 PM
Hi gcallaghan.
Thanks for reply, which version of Sencha Touch are you using?
I already tryed removeDocked but on 1.0.1 it doesn't solve the problem :(

gcallaghan
24 Jan 2011, 12:20 PM
Thanks for reply, which version of Sencha Touch are you using?
using 1.0.1

AndreaCammarata
24 Jan 2011, 12:26 PM
Thank you gcallaghan I've got this working and now I know what was my problem.
The following code works like a charm.




Ext.setup({
onReady: function() {
var tb = new Ext.Toolbar({
dock: 'top',
title: 'Hide Me!'
});

var myPanel = new Ext.Panel({
id: 'mainPanel',
bodyPadding:'0',
margin:'0',
fullscreen: true,
html: '<p>This is a Test</p>',
scroll: true,
dockedItems: [
tb,
{
xtype: 'toolbar',
dock: 'bottom',
items: [{
text: 'Hide Top Toolbar',
handler: function(){

//Hiding the top toolbar
tb.hide(false);

//Remove the toolbar
myPanel.removeDocked(tb,false);

},
}]
}]
});
}
});


The problem is that I was trying to call



myPanel.removeDocked('myToolbarId' ,false);


and not



myPanel.removeDocked(component ,false);


So if call removeDocked with the component object I want to remove (not the ID) everything works fine.


Hope this helps,
Thanks again gcallaghan.

mitchellsimoens
24 Jan 2011, 1:18 PM
Anyone know if this has been submitted as a bug? I looked but didn't see it. doComponentLayout should have technically solved this.

heringsfilet
31 Mar 2011, 1:22 AM
Hi there,

I tried to implement a "show" and "hide" functionality when connection to the internet is established or lost:


showNoInternetHint: function() {
var hint = app.views.viewport.getDockedComponent('hint');

if(hint.isVisible() === false){
navigator.notification.vibrate(500);
hint.setVisible(true);
app.views.viewport.addDocked(hint);
app.views.viewport.doComponentLayout();
}
},

hideNoInternetHint: function() {
var hint = app.views.viewport.getDockedComponent('hint');

if(hint.isVisible() === true){
hint.setVisible(false);
app.views.viewport.removeDocked(hint,false);
app.views.viewport.doComponentLayout();
}
}The methods get called correctly (there is the vibration). As item in the TabPanel there is a Panel which header is in the foreground and the hint is behind it.

This is the code for the "hint":


dockedItems: [{
xtype: 'panel',
id: 'hint',
ui: 'plain',
dock: 'top',
hidden: true,
items: [{
html: '<p class="hint">no connection!</p>'
}]
}],
Am I missing something else?

(UPDATE)
Following will work:


hint.setVisible(true);
app.views.viewport.addDocked(hint);
hint.doLayout();
app.views.viewport.doLayout();


and in the viewport:


listeners: {
afterlayout : function(pnl, lay){
var hint = this.getDockedComponent('hint');
if(hint.isVisible()){
this.body.setStyle('top', hint.getHeight() + 'px');
hint.setWidth(this.body.getWidth());
}
}
}

BlueCamel
31 Mar 2011, 5:48 PM
I was going to write a blog about it but decided it was just too much. I have attached source code to back this up.

So what is going on... I have a Panel that will hold everything. I have a top dock and bottom dock. Top dock holds a title and buttons only related to individual screens. The bottom dock is for the application as a whole like a Menu button or a Home button.


I really like how clean your implantation is in the example. I've been using the same pattern in a MVC app but let the parent do all the clean up through the cardswitch event. Based on your example I'm going to try and refactor my work and see if the design is cleaner.

Thanks for sharing.

vishalnnsingh
1 Apr 2011, 12:59 AM
Have some feelinh for the window guys, really want to see your code, but cannot. :)
Thanks

jep
20 Sep 2011, 7:45 AM
Related:

http://www.sencha.com/forum/showthread.php?147839-A-kludge-for-showing-hiding-docked-items&p=650976#post650976

extjsuser6
2 Mar 2013, 12:24 AM
hi , i had learn ext js 3.4 for 1 month. i created a viewport and i added panel in. Now , i want add listbox in my west panel but i read no listbox in extjs here. also , everybody wrote tree-panel.. can you help me for add listbox in panel ? 'personal list' etc.. thanks.


Ext.onReady (function(){


var k = {
xtype: 'textarea',
name: 'description',
hideLabel: true,
labelSeparator: '',
height: 100,
anchor: '100%' }

var ozellikliGrid = new Ext.grid.PropertyGrid({


//renderTo: Ext.getBody(),
width: 300,
// height : 400 ,
autoHeight: true,
propertyNames: {
tested: 'QA', // olamzsa bos olur ici
borderWidth: 'Kenar Genisligi'
},
source: { //gridin aldigi kaynaklar
'(isim)': 'Grid Ozellikleri ',
gruplama: false,
OtomatikSigdir: true,
// productionQuality: false,
tarih : new Date(Date.parse('01.01.2013')),
test: false,
versiyon: 0.01,
borderWidth: 3
}
});


var b ={
xtype :'panel',
region : 'center',
items:[
ozellikliGrid,
k

]
}

// a.add(x);
// EklenecekFormunAdi.remove('myPanelId');
var p1={
xtype :'panel',
title :'Kisiler',

items :[
{
frame :true,
width : 200,
height : 400

}
]
}



var p2={
id :'p2',
xtype :'panel',
title :'Kayit'

}


var w ={
title :'Yan',
xtype :'panel',
height : 100,
width : 200,
layout : 'accordion',
region :'west',
split : true,
frame : false,
collapsible : true,
layoutConfig:{
animate:true
},
items:[
p1,p2

]}

var a = new Ext.Viewport({

layout : 'border',
defaults : {
frame : true,
split : true
},

items :
[
w,
b,
{
region : 'north', // bas
split : false,
frame : true,
width : 400
}
]
});

// a.getComponent('centerViewPortId').add(ozellikliGrid);
/* <div id="prop-grid"></div>*/
});