-
Notifications
You must be signed in to change notification settings - Fork 2
Components
Ext JS의 기본구조는 컴포넌트로 구성된 위젯이라 볼수있다. 컴포넌트는 컴포넌트를 포함할수있고 컨테이너 혹은 차일드가 될 수 있다. 또한 컴포넌트를 커스터마이즈화 할 수 있으며 다양한 방법으로 사용 가능하다.
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 which allows them to participate in automated lifecycle management including instantiation, rendering, sizing and positioning, and destruction. 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.
컨테이너는 다른 컴포넌트를 포함하는 컴포넌트다. 네스트 혹은 트리 구조로 컴포넌트가 얽힐수있으며 컨테이너는 하위 컴포넌트들의 라이프사이클 (생성, 랜더링, 포지셔닝, 삭제)을 관리한다. 일반적으로 컴포넌트 계층구조는 Viewport를 최상위로 시작한다.
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 structure that is referred to as the Component hierarchy. Containers are responsible for managing the Component lifecycle of their children, which includes creation, rendering, sizing and positioning, and destruction. A typical application's Component hierarchy starts with a {@link Ext.container.Viewport Viewport} at the top, which has other Containers and/or Components nested within it:
{@img component_hierarchy.png Component Hierarchy}
차일드 컴포넌트는 item 변수를 통해 컨테이너에 추가된다. 아래 예제에서는 패널두개를 생성해 뷰포트의 일부로 추가시킨다. 두 패널이 뷰포트의 차일드 컴포넌트가 되는것이다.
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} to instantiate two {@link Ext.panel.Panel Panel}s, then adds those Panels as child Components of a Viewport:
@example
var childPanel1 = Ext.create('Ext.panel.Panel', {
title: 'Child Panel 1',
html: 'A Panel'
});
var childPanel2 = Ext.create('Ext.panel.Panel', {
title: 'Child Panel 2',
html: 'Another Panel'
});
Ext.create('Ext.container.Viewport', {
items: [ childPanel1, childPanel2 ]
});
컨테이너는 자식컴포넌트의 크기와 위치 등을 조절할 수 있으며 더 자세한 내용은 레이아웃을 보면 더 자세히 나와있다.
Containers use {@link Ext.layout.container.Container Layout Manager}s to size and position their child Components. For more information on Layouts and Containers please refer to the Layouts and Containers Guide.
See the Container Example for a working demo showing how to add Components to a Container using the items configuration.
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'.
The xtype
s for all Components are listed in the {@link Ext.Component API Docs for Component}.
The above example showed how to add already instantiated {@link Ext.Component Component}s to a {@link Ext.container.Container Container}.
In a large application, however, this is not ideal since not all of the Components need to be instantiated right away,
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}
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
by allowing a Container's children to be configured up front, but not instantiated until the Container determines it is necessary.
The following example code demonstrates lazy instantiation and rendering of a Container's Child components using a Tab Panel. Each tab has an event listener that displays an alert when the tab is rendered.
Ext.create('Ext.tab.Panel', {
renderTo: Ext.getBody(),
height: 100,
width: 200,
items: [
{
// Explicitly define the xtype of this Component configuration.
// This tells the Container (the tab panel in this case)
// to instantiate a Ext.panel.Panel when it deems necessary
xtype: 'panel',
title: 'Tab One',
html: 'The first tab',
listeners: {
render: function() {
Ext.MessageBox.alert('Rendered One', 'Tab One was rendered.');
}
}
},
{
// this component configuration does not have an xtype since 'panel' is the default
// xtype for all Component configurations in a Container
title: 'Tab Two',
html: 'The second tab',
listeners: {
render: function() {
Ext.MessageBox.alert('Rendered One', 'Tab Two was rendered.');
}
}
}
]
});
Running this code results in an immediate alert for the first tab. This happens because it is the default active tab, and so its Container Tab Panel instantiates and renders it immediately.
{@img lazy_render1.png Lazy Render 1}
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
needed, since the {@link Ext.Component#render render}
event did not fire until the tab was activated.
{@img lazy_render2.png Lazy Render 2}
For a working demo see the Lazy Instantiation Example
All {@link Ext.Component Component}s have built in {@link Ext.Component#method-show show} and {@link Ext.Component#method-hide hide} methods. 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:
var panel = Ext.create('Ext.panel.Panel', {
renderTo: Ext.getBody(),
title: 'Test',
html: 'Test Panel',
hideMode: 'visibility' // use the CSS visibility property to show and hide this component
});
panel.hide(); // hide the component
panel.show(); // show the component
Floating {@link Ext.Component Component} are positioned outside of the document flow using CSS absolute positioning, and do not participate in their Containers' layout. 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.
var panel = Ext.create('Ext.panel.Panel', {
width: 200,
height: 100,
floating: true, // make this panel an absolutely-positioned floating component
title: 'Test',
html: 'Test Panel'
});
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}
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.
Floating Components are automatically rendered to the document body the first time their {@link Ext.Component#method-show show} method is called:
panel.show(); // render and show the floating panel
Here are a few other configurations and methods to make note of related to floating components:
-
{@link Ext.Component#cfg-draggable draggable}
- enables dragging of a floating Component around the screen. -
{@link Ext.Component#cfg-shadow shadow}
- customizes the look of a floating Component's shadow. -
{@link Ext.Component#method-alignTo alignTo()}
- aligns a floating Component to a specific element. -
{@link Ext.Component#method-center center()}
- centers a floating Component in its Container.
For a working demo of floating Component features see the Floating Panel Example.
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.
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 includes automated rendering when needed, automatic sizing and positioning of Components when managed by an appropriate layout manager, and automated destruction on removal from a {@link Ext.Container Container}.
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, and then has to render and manage it from outside.
The {@link Ext.Class Class System} makes it easy to extend existing Components. The following example creates a subclass of {@link Ext.Component} without adding any additional functionality:
Ext.define('My.custom.Component', {
extend: 'Ext.Component'
});
Ext JS uses the Template method pattern to delegate to subclasses, behavior which is specific only to that subclass.
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. Each class implements its own special behavior while allowing the other classes in the inheritance chain to continue to contribute their own logic.
An example is the render function. render
is a private method defined in {@link Ext.Component Component}'s superclass,
{@link Ext.AbstractComponent AbstractComponent} that is responsible for initiating the rendering phase of the Component lifecycle.
render
must not be overridden, but it calls onRender
during processing to allow the subclass implementor to add an onRender
method to perform class-specific processing. Every onRender
method must call its superclass' onRender
method before "contributing" its extra logic.
The diagram below illustrates the functioning of the onRender
template method.
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.
It calls this.onRender
which is the implementation within the current subclass (if implemented).
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.
{@img template_pattern.png Template Pattern}
Here is an example of a Component subclass that implements the onRender
method:
Ext.define('My.custom.Component', {
extend: 'Ext.Component',
onRender: function() {
this.callParent(arguments); // call the superclass onRender method