Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ExtJS - Fill and Auto Height

I'm using ExtJS (html/css) and I've got a question regarding Layout. Example:

|--------|
|        |
|        |
|        |
|        |
|        |
|--------|
|        |
|        |
|--------|

The combined height (they don't have any padding, margin etc.) is 100% of it's parent container. Preferably, it's two panels somehow stacked on each other.

The problem is that I don't know the height of neither the top panel nor the bottom panel (it's not fixed, and may change since the content within the panels may change, it's two menus.) I need the top panel to fill out the remaining space, or have a scrollbar if needed.

It's not that important that the solution is pure ExtJS, it's just that the container for the two panels is an ExtJS panel, the content of the two panels inside is plain html driven by javascript.

Anybody who has a clue where to start?

Edit
I think a part of the problem is the lack of the "resize" event. I think I can get away with some semi-dynamic/static solution and try to calculate the height of the lower panel

like image 826
Onkelborg Avatar asked Oct 27 '10 16:10

Onkelborg


3 Answers

There may be a easier way. In ExtJS 4 (I haven't tested in 3 but it might work) when using the vbox layout if a child item has a flex of 0 or undefined the layout manager will not adjust the height of that item.

So for your example, the top panel would have a flex of 1 and the bottom panel would have a flex of 0:

Ext.create("widget.panel", {
  renderTo: Ext.getBody(),
  height: 300, width: 400,
  layout: { type: 'vbox', pack: 'start', align: 'stretch' },
  items: [{
    // our top panel
    xtype: 'container', 
    flex: 1,             // take remaining available vert space
    layout: 'fit', 
    autoScroll: true, 
    items: [{ 
      xtype: 'component', 
      // some long html to demonstrate scrolling
      html: '<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>'
    }] 
  },{ 
    // our bottom panel
    xtype: 'container', 
    flex: 0,             // dont change height of component (i.e. let children dictate size.)
    items: [{ 
      xtype: 'button', 
      height: 200, 
      text: 'Hello World'
    }]
  }]
});

Now the bottom panel will just take the height of any child components and the top panel will take the remaining available height.

like image 98
Andy Avatar answered Nov 04 '22 03:11

Andy


This is not an easy problem to solve. By your description of the problem Panel 2 must have autoHeight: true, but there is no way to tell the browser or Ext to automatically size the top panel according to that.

The best I can come up with is to do it manually on a timer:

  • Create an outer container for both panels with an absolute layout, fixed height. Apply a custom "position: relative" style to it.
  • Panel 1 has config x: 0, y: 0, anchor: "100% 100%", autoScroll: true
  • Panel 2 is autoHeight: true with custom style: "top: auto; bottom: 0"
  • Run a task on an interval of 1 sec or so that checks the height of Panel 2, and assigns that height to a padding-bottom style on Panel 1
like image 3
divestoclimb Avatar answered Nov 04 '22 04:11

divestoclimb


If I get the question correct- the two panels should not have a fixed size UNLESS they have content, in which case they scroll? Typically I would suggest that at least one of the panels represents 'master' content and has a fixed size. Otherwise, this should work:

layout:'vbox',
layoutConfig: {
    align : 'stretch',
    pack  : 'start',
},
items: [
    {html:'panel 1', flex:1},
    {html:'panel 2', flex:2}
]

Simply give that config to the 'holding' element and then setup 'panel 1' and 'panel 2' as you see fit (i.e. replace '{html:'panel 1', flex:1}' with the name of the component)

like image 3
SW4 Avatar answered Nov 04 '22 04:11

SW4