Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / docs / guides / components / README.md
1 # Components
2 ______________________________________________
3
4 An Ext JS application's UI is made up of one or many widgets called {@link Ext.Component Component}s. All Components are subclasses of the {@link Ext.Component} class
5 which allows them to participate in automated lifecycle management including instantiation, rendering, sizing and positioning, and destruction.
6 Ext JS provides a wide range of useful Components out of the box, and any Component can easily be extended to create a customized Component.
7
8 ## The Component Hierarchy
9
10 A {@link Ext.container.Container Container} is a special type of Component that can contain other Components. A typical application is made up of many nested Components in a tree-like
11 structure that is referred to as the Component hierarchy.  Containers are responsible for managing the Component lifecycle of their children, which includes creation, rendering,
12 sizing and positioning, and destruction. A typical application's Component hierarchy starts with a {@link Ext.container.Viewport Viewport} at the top,
13 which has other Containers and/or Components nested within it:
14
15 {@img component_hierarchy.png Component Hierarchy}
16
17 Child Components are added to a Container using the Container's {@link Ext.container.Container#cfg-items items} configuration property.  This example uses {@link Ext#create Ext.create}
18 to instantiate two {@link Ext.panel.Panel Panel}s, then adds those Panels as child Components of a Viewport:
19
20     @example
21     var childPanel1 = Ext.create('Ext.panel.Panel', {
22         title: 'Child Panel 1',
23         html: 'A Panel'
24     });
25
26     var childPanel2 = Ext.create('Ext.panel.Panel', {
27         title: 'Child Panel 2',
28         html: 'Another Panel'
29     });
30
31     Ext.create('Ext.container.Viewport', {
32         items: [ childPanel1, childPanel2 ]
33     });
34
35 Containers use {@link Ext.layout.container.Container Layout Manager}s to size and position their child Components.
36 For more information on Layouts and Containers please refer to the [Layouts and Containers Guide](guide/layouts_and_containers).
37
38 See the [Container Example](guides/components/examples/container/index.html) for a working demo showing how to add Components to a Container using the items configuration.
39
40 ## XTypes and Lazy Instantiation
41
42 Every Component has a symbolic name called an `{@link Ext.Component#cfg-xtype xtype}`. For example {@link Ext.panel.Panel} has an `xtype` of 'panel'.
43 The `xtype`s for all Components are listed in the {@link Ext.Component API Docs for Component}.
44 The above example showed how to add already instantiated {@link Ext.Component Component}s to a {@link Ext.container.Container Container}.
45 In a large application, however, this is not ideal since not all of the Components need to be instantiated right away,
46 and some Components might never be instantiated depending on how the application is used. For example an application that uses a {@link Ext.tab.Panel Tab Panel}
47 will only need the contents of each tab to be rendered if and when each tab is clicked on by the user. This is where `xtype`s come in handy
48 by allowing a Container's children to be configured up front, but not instantiated until the Container determines it is necessary.
49
50 The following example code demonstrates lazy instantiation and rendering of a Container's Child components using a Tab Panel.
51 Each tab has an event listener that displays an alert when the tab is rendered.
52
53     Ext.create('Ext.tab.Panel', {
54         renderTo: Ext.getBody(),
55         height: 100,
56         width: 200,
57         items: [
58             {
59                 // Explicitly define the xtype of this Component configuration.
60                 // This tells the Container (the tab panel in this case)
61                 // to instantiate a Ext.panel.Panel when it deems necessary
62                 xtype: 'panel',
63                 title: 'Tab One',
64                 html: 'The first tab',
65                 listeners: {
66                     render: function() {
67                         Ext.MessageBox.alert('Rendered One', 'Tab One was rendered.');
68                     }
69                 }
70             },
71             {
72                 // this component configuration does not have an xtype since 'panel' is the default
73                 // xtype for all Component configurations in a Container
74                 title: 'Tab Two',
75                 html: 'The second tab',
76                 listeners: {
77                     render: function() {
78                         Ext.MessageBox.alert('Rendered One', 'Tab Two was rendered.');
79                     }
80                 }
81             }
82         ]
83     });
84
85 Running this code results in an immediate alert for the first tab. This happens because it is the default active tab,
86 and so its Container Tab Panel instantiates and renders it immediately.
87
88 {@img lazy_render1.png Lazy Render 1}
89
90 The alert for the second tab does not get displayed until the tab is clicked on. This shows that the tab was not rendered until
91 needed, since the `{@link Ext.Component#render render}` event did not fire until the tab was activated.
92
93 {@img lazy_render2.png Lazy Render 2}
94
95 For a working demo see the [Lazy Instantiation Example](guides/components/examples/lazy_instantiation/index.html)
96
97 ## Showing and Hiding
98
99 All {@link Ext.Component Component}s have built in {@link Ext.Component#method-show show} and {@link Ext.Component#method-hide hide} methods.
100 The default CSS method used to hide the Component is "display: none", but this can be changed using the {@link Ext.Component#cfg-hideMode hideMode} configuration:
101
102     var panel = Ext.create('Ext.panel.Panel', {
103         renderTo: Ext.getBody(),
104         title: 'Test',
105         html: 'Test Panel',
106         hideMode: 'visibility' // use the CSS visibility property to show and hide this component
107     });
108
109     panel.hide(); // hide the component
110
111     panel.show(); // show the component
112
113 ## Floating Components
114
115 Floating {@link Ext.Component Component} are positioned outside of the document flow using CSS absolute positioning, and do not participate in their Containers' layout.
116 Some Components such as {@link Ext.window.Window Window}s are floating by default, but any Component can be made floating using the {@link Ext.Component#cfg-floating floating} configuration.
117
118     var panel = Ext.create('Ext.panel.Panel', {
119         width: 200,
120         height: 100,
121         floating: true, // make this panel an absolutely-positioned floating component
122         title: 'Test',
123         html: 'Test Panel'
124     });
125
126 The above code instantiates a {@link Ext.panel.Panel Panel} but does not render it. Normally a Component either has a `{@link Ext.Component#cfg-renderTo renderTo}`
127 configuration specified, or is added as a child Component of a {@link Ext.container.Container Container}, but in the case of floating Components neither of these is needed.
128 Floating Components are automatically rendered to the document body the first time their {@link Ext.Component#method-show show} method is called:
129
130     panel.show(); // render and show the floating panel
131
132 Here are a few other configurations and methods to make note of related to floating components:
133
134 - `{@link Ext.Component#cfg-draggable draggable}` - enables dragging of a floating Component around the screen.
135 - `{@link Ext.Component#cfg-shadow shadow}` - customizes the look of a floating Component's shadow.
136 - `{@link Ext.Component#method-alignTo alignTo()}` - aligns a floating Component to a specific element.
137 - `{@link Ext.Component#method-center center()}` - centers a floating Component in its Container.
138
139 For a working demo of floating Component features see the [Floating Panel Example](guides/components/examples/floating_panel).
140
141 ## Creating Custom Components
142
143 ### Composition or Extension
144
145 When creating a new UI class, the decision must be made whether that class should own an instance of a {@link Ext.Component Component}, or to extend that Component.
146
147 It is recommended to extend the nearest base class to the functionality required. This is because of the automated lifecycle management Ext JS provides which
148 includes automated rendering when needed, automatic sizing and positioning of Components when managed by an appropriate layout manager,
149 and automated destruction on removal from a {@link Ext.Container Container}.
150
151 It is easier to write a new class which is a Component and can take its place in the Component hierarchy rather than a new class which has an Ext JS Component,
152 and then has to render and manage it from outside.
153
154 ### Subclassing
155
156 The {@link Ext.Class Class System} makes it easy to extend existing Components.  The following example creates a subclass of {@link Ext.Component} without
157 adding any additional functionality:
158
159     Ext.define('My.custom.Component', {
160         extend: 'Ext.Component'
161     });
162
163 ### Template Methods
164
165 Ext JS uses the [Template method pattern](http://en.wikipedia.org/wiki/Template_method_design_pattern) to delegate to subclasses, behavior which is specific only to that subclass.
166
167 The meaning of this is that each class in the inheritance chain may "contribute" an extra piece of logic to certain phases in the Component's lifecycle.
168 Each class implements its own special behavior while allowing the other classes in the inheritance chain to continue to contribute their own logic.
169
170 An example is the render function. `render` is a private method defined in {@link Ext.Component Component}'s superclass,
171 {@link Ext.AbstractComponent AbstractComponent} that is responsible for initiating the rendering phase of the Component lifecycle.
172 `render` must not be overridden, but it calls `onRender` during processing to allow the subclass implementor to add an `onRender`
173 method to perform class-specific processing. Every `onRender` method must call its superclass' `onRender` method before "contributing" its extra logic.
174
175 The diagram below illustrates the functioning of the `onRender` template method.
176
177 The `render` method is called (This is done by a Container’s layout manager). This method may not be overridden and is implemented by the Ext base class.
178 It calls `this.onRender` which is the implementation within the current subclass (if implemented).
179 This calls the superclass version which calls its superclass version etc. Eventually, each class has contributed its functionality, and control returns to the `render` function.
180
181 {@img template_pattern.png Template Pattern}
182
183 Here is an example of a Component subclass that implements the `onRender` method:
184
185     Ext.define('My.custom.Component', {
186         extend: 'Ext.Component',
187         onRender: function() {
188             this.callParent(arguments); // call the superclass onRender method
189
190             // perform additional rendering tasks here.
191         }
192     });
193
194 It is important to note that many of the template methods also have a corresponding event. For example the {@link Ext.Component#event-render render}
195 event is fired after the Component is rendered.  When subclassing, however, it is it is essential to use template methods to perform class logic at
196 important phases in the lifecycle and *not* events. Events may be programmatically suspended, or may be stopped by a handler.
197
198 Below are the template methods that can be implemented by subclasses of Component:
199
200 - `initComponent`
201 This method is invoked by the constructor. It is used to initialize data, set up configurations, and attach event handlers.
202 - `beforeShow`
203 This method is invoked before the Component is shown.
204 - `onShow`
205 Allows addition of behavior to the show operation. After calling the superclass’s onShow, the Component will be visible.
206 - `afterShow`
207 This method is invoked after the Component is shown.
208 - `onShowComplete`
209 This method is invoked after the `afterShow` method is complete
210 - `onHide`
211 Allows addition of behavior to the hide operation. After calling the superclass’s onHide, the Component will be hidden.
212 - `afterHide`
213 This method is invoked after the Component has been hidden
214 - `onRender`
215 Allows addition of behavior to the rendering phase. After calling the superclass’s onRender,
216 the Component's Element will exist. Extra DOM processing may be performed at this stage to complete the desired structure of the Component.
217 - `afterRender`
218 Allows addition of behavior after rendering is complete. At this stage the Component’s Element will have been styled according to the configuration,
219 will have had any configured CSS class names added, and will be in the configured visibility and the configured enable state.
220 - `onEnable`
221 Allows addition of behavior to the enable operation. After calling the superclass’s onEnable, the Component will be enabled.
222 - `onDisable`
223 Allows addition of behavior to the disable operation. After calling the superclass’s onDisable, the Component will be disabled.
224 - `onAdded`
225 Allows addition of behavior when a Component is added to a Container. At this stage, the Component is in the parent Container's collection of child items.
226 After calling the superclass's onAdded, the ownerCt reference will be present, and if configured with a ref, the refOwner will be set.
227 - `onRemoved`
228 Allows addition of behavior when a Component is removed from its parent Container. At this stage, the Component has been removed from its parent Container's
229 collection of child items, but has not been destroyed (It will be destroyed if the parent Container's autoDestroy is true, or if the remove call was passed a truthy second parameter).
230 After calling the superclass's onRemoved, the ownerCt and the refOwner will not be present.
231 - `onResize`
232 Allows addition of behavior to the resize operation.
233 - `onPosition`
234 Allows addition of behavior to the position operation.
235 - `onDestroy`
236 Allows addition of behavior to the destroy operation. After calling the superclass’s onDestroy, the Component will be destroyed.
237 - `beforeDestroy`
238 This method is invoked before the Component is destroyed.
239 - `afterSetPosition`
240 This method is invoked after the Components position has been set.
241 - `afterComponentLayout`
242 This method is invoked after the Component is laid out.
243 - `beforeComponentLayout`
244 This method is invoked before the Component is laid out.
245
246 ### Which Class To Extend
247
248 Choosing the best class to extend is mainly a matter of efficiency, and which capabilities the base class must provide.
249 There has been a tendency to always extend {@link Ext.Panel} whenever any set of UI Components needs to be rendered and managed.
250
251 The Panel class has many capabilities:
252
253 - Border
254 - Header
255 - Header tools
256 - Footer
257 - Footer buttons
258 - Top toolbar
259 - Bottom toolbar
260 - Containing and managing child Components
261
262 If these are not needed, then using a Panel is a waste of resources.
263
264 #### Component
265
266 If the required UI Component does not need to contain any other Components, that is, if it just to encapsulate some form of HTML which performs the requirements,
267 then extending {@link Ext.Component} is appropriate. For example, the following class is a Component that wraps an HTML image element, and allows setting
268 and getting of the image's `src` attribute. It also fires a `load` event when the image is loaded:
269
270     Ext.define('Ext.ux.Image', {
271         extend: 'Ext.Component', // subclass Ext.Component
272         alias: 'widget.managedimage', // this component will have an xtype of 'managedimage'
273         autoEl: {
274             tag: 'img',
275             src: Ext.BLANK_IMAGE_URL,
276             cls: 'my-managed-image'
277         },
278
279         // Add custom processing to the onRender phase.
280         // Add a ‘load’ listener to the element.
281         onRender: function() {
282             this.autoEl = Ext.apply({}, this.initialConfig, this.autoEl);
283             this.callParent(arguments);
284             this.el.on('load', this.onLoad, this);
285         },
286
287         onLoad: function() {
288             this.fireEvent('load', this);
289         },
290
291         setSrc: function(src) {
292             if (this.rendered) {
293                 this.el.dom.src = src;
294             } else {
295                 this.src = src;
296             }
297         },
298
299         getSrc: function(src) {
300             return this.el.dom.src || this.src;
301         }
302     });
303
304 Usage:
305
306     var image = Ext.create('Ext.ux.Image');
307
308     Ext.create('Ext.panel.Panel', {
309         title: 'Image Panel',
310         height: 200,
311         renderTo: Ext.getBody(),
312         items: [ image ]
313     })
314
315     image.on('load', function() {
316         console.log('image loaded: ', image.getSrc());
317     });
318
319     image.setSrc('http://www.sencha.com/img/sencha-large.png');
320
321 See the [Managed Image Example](guides/components/examples/managed_image/index.html) for a working demo. This example is for demonstration purposes only -
322 the {@link Ext.Img} class should be used for managing images in a real world application.
323
324 #### Container
325
326 If the required UI Component is to contain other Components, but does not need any of the previously mentioned additional capabilities of a {@link Ext.Panel Panel},
327 then {@link Ext.container.Container} is the appropriate class to extend. At the Container level, it is important to remember which {@link Ext.layout.container.Container Layout}
328 is to be used to render and manage child Components.
329
330 Containers have the following additional template methods:
331
332 - `onBeforeAdd`
333 This method is invoked before adding a new child Component. It is passed the new Component, and may be used to modify the Component, or prepare the Container in some way. Returning false aborts the add operation.
334 - `onAdd`
335 This method is invoked after a new Component has been added. It is passed the Component which has been added. This method may be used to update any internal structure which may depend upon the state of the child items.
336 - `onRemove`
337 This method is invoked after a new Component has been removed. It is passed the Component which has been removed. This method may be used to update any internal structure which may depend upon the state of the child items.
338 - `beforeLayout`
339 This method is invoked before the Container has laid out (and rendered if necessary) its child Components.
340 - `afterLayout`
341 This method is invoked after the Container has laid out (and rendered if necessary) its child Components.
342
343 #### Panel
344
345 If the required UI Component must have a header, footer, or toolbars, then Ext.Panel is the appropriate class to extend.
346
347 *Important*: A Panel is a Container. It is important to remember which {@link Ext.layout.container.Container Layout} is to be used to render and manage child Components.
348
349 Classes which extend Ext.Panel are usually highly application-specific and are generally used to aggregate other UI Components
350 (Usually Containers, or form Fields) in a configured layout, and provide means to operate on the contained Components by means
351 of controls in the {@link Ext.panel.Panel#cfg-tbar tbar} and the {@link Ext.panel.Panel#cfg-bbar bbar}.
352
353 Panels have the following additional template methods:
354
355 - `afterCollapse`
356 This method is invoked after the Panel is Collapsed.
357 - `afterExpand`
358 This method is invoked after the Panel is expanded
359 - `onDockedAdd`
360 This method is invoked after a docked item is added to the Panel
361 - `onDockedRemove`
362 This method is invoked after a docked item is removed from the Panel