About containers

At this point, we know all the steps of the lifecycle. If you remember, in the rendering phase there's a step where the children of the components are rendered too. Now we're going to learn about containers and how we can add children to a component.

The Ext.container.Container class is responsible for managing children and to arrange those using layouts. If we want our class to contain other components, we should extend from this class. It's worth saying that this class extends from Ext.Component, so we'll be able to use the component lifecycle in our subclasses too:

About containers

All classes that extend Ext.Container will be able to have children using the items property or use the add method to append a new component as a child. Let's check out the following code snippet:

Ext.define("MyApp.sample.MyContainer",{
  extend: "Ext.container.Container",   //Step 1
  border: true,
  padding: 10,
  initComponent: function(){
    var me = this;
    Ext.each(me.items,function(item){  //Step 2
      item.style = {
        backgroundColor:"#f4f4f4",
          border:"1px solid #333"
      };
      item.padding = 10;
      item.height = 100;
    });
    me.callParent();
  },
  onRender: function(){
    var me = this;
    me.callParent(arguments);
    if( me.border ){  //Step 3
      me.el.setStyle( "border" , "1px solid #333" );
    }
  }
});

In the code example, we set var me=this;. This is in order to present that me or this is referring to the scope of the current object/class being handled or manipulated.

The previous class extends from the Ext.container.Container class. Now we can use the layout system to arrange the children of the container.

When extending from the Container class, we can use the items property to define the children of the main container. We're looping the items property, which is an array, to add some basic styles. We're using the initComponent method that is executed automatically in the creation phase. We shouldn't forget to call the super class by executing the callParent method.

The last step overrides the onRender method. After executing the callParent method, we can have access to the el property that is a reference to the main node of our component. If the border property is set to true, we will add CSS styles to display a border around the main element's node.

Once we have defined our class, we can create an instance of it. Let's create an HTML page including the Ext library and our class in order to execute the following code:

Ext.onReady(function(){
  Ext.create("MyApp.sample.MyContainer",{
    renderTo: Ext.getBody(),
    items: [{
      xtype: "component",
      html: "Child Component one"
    },{
      xtype: "component",
      html: "Child Component two"
    }]
  });
});

We're creating the instance of our class as usual. We added the items property as an array of components. We can define as many components as we need because our class is a container.

In this example, we are using the xtype property to define each inner component, but we could also create an instance of the component's child and then pass the reference into the items array.

Tip

Using the xtype property allows us to create components easier than handling the complete class name, and we also use fewer lines of code. When the main container is created, all their children are created as well. We'll find all the available xtype properties in the documentation. Usually xtype is next to the class name. To see all the xtypes available in Ext JS, visit http://docs.sencha.com/extjs/5.1/5.1.1-apidocs/#!/api/Ext.enums.Widget.

The following screenshot shows three components. One is the main component that contains two children. We have achieved this by extending from the Container class and using the items property.

About containers

When using containers, we can use a property called defaults that allows us to apply the same properties (default values/configurations) to all of the children in the main container. Let's add some default values to our previous example:

Ext.onReady(function(){
  Ext.create("MyApp.sample.MyContainer",{
    renderTo: Ext.getBody(),
 defaults: {
 xtype : "component",
 width : 100
 },
    items  :[{
      html:"Child Component one" //xtype:"component",
    },{
      html:"Child Component two"  //xtype:"component",
    }]
  });
});

The defaults property receives an object containing all the configurations that we want to apply to the components inside the items array. In this case, we have added the width and xtype properties. This way, we don't have to repeat the same lines of code for each component:

About containers

As we can see in the previous screenshot, the sizes of the two children are the same. We can also override a default property by simply adding the property that we want to be different to the specific child.

Tip

Every time, we find properties that are repeated in each child component. It's recommended to use the defaults property to apply all the properties defined in defaults at once. This will reduce the lines of code and will prevent code duplication. If we define the same property in any of the children, the default value will be overridden.

Types of containers

Ext JS uses several components as containers, and each one of them has its own foundation from the Ext.container.Container class. Some of the most common containers are as follows:

Note that each container has the property layout; this property will give us the ability to present its child components in different ways to arrange them.

The viewport

The viewport, as we mentioned before, represents the viewable application area and the best practice is that there has to be only one viewport created on the web page. To create a basic viewport, let's use the following code:

Ext.onReady(function(){
  Ext.create('Ext.container.Viewport',{
    padding:'5px',
    layout:'auto',
    style : {
      'background-color': '#fc9',
      'color': '#000'
    },
  html:'This is application area'
  });
});
Tip

It's recommended that no matter what application you build, whether plain code or an application using MVC or MVVM architecture, the use of the viewport component is needed.

The panel

The panel component (Ext.panel.Panel) is one of the most commonly used components in Ext JS. A panel can contain other panels or even other components.

Let's create our first panel by instantiating the Ext.panel.Panel class. We need to create an HTML page, import the Ext JS library, and then execute the following code when the DOM is ready to be used:

Ext.onReady(function(){
  var MyPanel = Ext.create("Ext.panel.Panel",{
    renderTo: Ext.getBody(),
    title: 'My first panel...',
    width: 300,
    height: 220,
    html:'<b>Here</b> goes some <i>content</i>..!'
  });
});

As you can notice, we have created the instance of the Panel class in the same way we created a component in previous examples (the container examples). The only difference is that we have added a new configuration called title with the text we want to show as the title of our panel.

The panel

Panels versus containers

As we have seen, containers create a basic HTML DOM element containing HTML or child components that we insert into the container. Panels, on the other hand, create extra sections (such as header and tools) and have more functionality (methods and functions) than containers. Some highlights and common parts of the panel are shown in the following screenshot:

Panels versus containers

The Window component

A window is basically a floating panel with more features. The Window component extends from the Panel class. This means that we can use all the methods and properties that the panel has. Also, we can drag a window from the header bar, close it, and maximize it, among other things. Let's create a .html file as follows that imports the Ext library and runs the code when the DOM is ready:

  var win = Ext.create("Ext.window.Window",{
    title: 'My first window',
    width: 300,
    height: 200,
    maximizable: true,
    html: 'this is my first window'
  });
  win.show();

Another alternative for this code can be:

 Ext.create("Ext.window.Window",{
    title: 'My first window',
    width: 300,
    height: 200,
    maximizable: true,
    html: 'this is my first window'
 }).show();

The only difference in our previous code and the panel's code is the maximizable property that allows us to maximize the window. We've removed the renderTo property too and used the show method to render and display the window.

The Window component

By default, the window is closable, but we can make it non-closable by setting the closable property to false. We can move the window across the screen by dragging the header. We can also resize the window with the mouse for each of the four sides.

There are many more options for the window component. You should take a look at the API documentation and play around with this component.