Beruflich Dokumente
Kultur Dokumente
BASICO
Sintaxis:
Ext.define((String) className, (Object) classMembers, (Optional Function) onClassCreatedCallback);
Parámetros:
className: es el nombre completo de la clase en formato punto-nombre de la ubicación/proyecto.
classMembers: es un objeto que representa una colección clases miembro en pares clave-valor (literales de
objeto Javascript).
onClassCreatedCallback: es una función opcional de llamada que se invoca cuando todas las dependencias
de esta clase están listas y la clase en sí está totalmente creada.
Nota: Ext.Base es la raíz de todas las clases creadas con Ext.define. Todas las clases en Ext JS heredan de
Ext.Base.
Ext.define('Student',
{
name: 'unnamed',
getName: function(){
return "El nombre del Estudiante es:" + this.name;
}
}, function(){
alert('Objeto Student se creó');
});
El ejemplo anterior define la clase Student con una variable miembro 'name' y un método getName ().
Según la sintaxis de Ext.define, el primer parámetro 'Student' es el nombre de la clase. El segundo parámetro
es un objeto de JavaScript que contiene el name y getName (), y el tercer parámetro (opcional) es la función o
método que se llamará después de crear la clase "Student".
De esta manera se puede crear una clase personalizada en Ext JS.
El siguiente ejemplo muestra cómo crear un objeto de la clase Student y llamar al método getName ().
Definir Constructor:
Para definir una clase personalizada con el constructor, agregue el constructor del nombre de la función como un
miembro de la clase:
Ext.define('Student', {
name: 'unnamed',
getName: function(){
return 'El nombre del Estudiante es ' + this.name;
},
constructor: function(studentName){
if(studentName)
this.name = studentName;
}
});
return {
constructor: function(name){
this.name = name;
},
getName: function(){
alert('El nombre del Estudiante es ' + this.name);
}
};
});
No puede acceder la propiedad name directamente, ya que es un miembro privado. Use el método getName
() en el objeto student para acceder al name.
Declare miembros estáticos en la clase Ext JS usando el parámetro 'statics' como se muestra a continuación.
Ext.define('Student',
{
name: 'unnamed',
getName: function(){
alert('Student name is ' + this.name);
},
constructor: function(studentName){
if(studentName)
this.name = studentName;
},
statics:
{
getSchoolName: function(){
return "XYZ";
}
}
});
Como puede ver en el ejemplo anterior, la función getSchoolName () se define dentro del objeto de
parámetro estático. Así que ahora puedes llamarlo como Student.getSchoolName ().
constructor: function(name){
if(name){
this.name = name;
}
},
getName: function(){
alert("My name is " + this.name);
}
});
Ahora, defina la clase de Student con extend: 'Person' en la sección de configuración como se muestra a
continuación.
Ext.define('Student',
{
extend: 'Person',
schoolName: 'Unknown',
getSchoolName: function(){
alert("El nombre de mi Escuela es " + this.schoolName);
}
});
Como puede ver arriba, la clase Student hereda la clase Person usando la palabra clave de extend. Así que
ahora, podemos llamar al método getName () en el objeto Student, que a su vez llamará al método getName
() de la clase Person.
Nota: la mayoría de las veces tendrá que extender los componentes Ext JS en su aplicación para usar la
funcionalidad predeterminada del componente y agregar una funcionalidad personalizada.
Mixins:
Mixins fue introducido desde Ext JS 4. Mixins nos permite usar funciones de una clase como una función de
otra clase sin herencia.
Los mixins se pueden definir utilizando la palabra clave mixins y especificando el valor como un objeto JSON
donde el nombre de una propiedad debe ser el nombre del método que desea usar y el valor de una
propiedad será el nombre de la clase donde se define el método.
Ext.define('Person', {
name: 'Unknown',
constructor: function(name) {
if (name) {
this.name = name;
}
},
getName: function() {
alert("Mi nombre es " + this.name);
},
eat: function(foodType) {
alert("Estoy comiendo " + foodType);
}
});
Ext.define('Student', {
schoolName: '',
constructor: function(schoolName) {
this.schoolName = schoolName || 'Unknown'
},
mixins: {
eat: 'Person'
},
getSchoolName: function() {
alert("Soy un estudiante de " + this.schoolName);
}
});
En el ejemplo anterior, la clase Student define los mixins y especifica 'eat' como nombre de propiedad y
'Person' como valor donde se define el método eat (). Así que ahora puede llamar al método studentObj.eat
() como si estuviera definido en la clase Student.
Config:
Ext JS tiene una característica llamada Config. Config permite declarar propiedades públicas con valores
predeterminados que serán completamente encapsulados desde otros miembros de la clase. Las
propiedades que se declaran a través de Config, tendrán los métodos get () y set () automáticamente si la
clase no tiene estos métodos ya definidos.
Las propiedades en Config se pueden definir utilizando la palabra clave config con el objeto JSON como un
valor donde puede definir propiedades. Considere el siguiente ejemplo.
Ext.define('Student', {
config:
{
name: 'unnamed',
schoolName: 'Unknown'
},
constructor: function(config){
this.initConfig(config);
}
});
En el ejemplo anterior, la clase de Student incluye dos propiedades Config: name y schoolName con el valor
predeterminado "undefined". En el constructor, llamamos this.initConfig (config). Esto creará métodos get y
set para todas las propiedades de config. Debemos llamar a this.initConfig (config) en el constructor para
inicializar getters y setters. El método get devuelve un valor de una propiedad config y el método set se usa
para asignar un nuevo valor a una propiedad config.
El nombre del método get empezará con get y el sufijo con el nombre de la propiedad como get <config
property name> () y de la misma manera, el método set se nombrará como set <config property name> (). El
sufijo en los nombres de método get y set empezará con letra capital. Por lo tanto, los nombres de método
get y set para el nombre anterior y las propiedades Config de schoolName serán getName (), setName (),
getSchoolName () y setSchoolName ().
El siguiente ejemplo muestra cómo acceder al método get y set de la clase de Student anterior.
Ext.define('Student', {
config:
{
name: 'unnamed',
schoolName: 'Unknown'
},
constructor: function(config){
this.initConfig(config);
}
});
newStudent.getName();//salida: XYZ
newStudent.getSchoolName();//salida: ABC School
newStudent.setName('John');
newStudent.setSchoolName('New School');
newStudent.getName();//salida: John
newStudent.getSchoolName();//salida: New School
Como puede ver en el ejemplo anterior, no hemos definido los métodos getName (), setName () y
getSchoolName (), setSchoolName () en el objeto Student. Fue creado automáticamente para las propiedades
de config por Ext JS API.
Tenga en cuenta que no puede asignar el valor de la propiedad config directamente igual que la propiedad
de clase normal. Debe usar el método set para asignar un valor a la propiedad config. Por ejemplo, lo
siguiente NO es válido. No asigna un valor a la propiedad name, sino que crea otra propiedad name en la
instancia.
Setters personalizados:
Usted ha visto que los métodos get y set se crean automáticamente para la propiedad config. Pero, cómo
agregar lógica adicional antes o después de que asignemos un valor a la propiedad config porque los métodos
get y set se administran internamente. La respuesta es setters personalizados (configuradores personalizados).
Los setters personalizados permiten agregar lógica adicional a sus setters. Hay dos setters personalizados:
apply y update.
El método apply () para la propiedad config nos permite agregar un poco de lógica adicional antes de asignar
el valor a la propiedad config. El nombre del método apply debe comenzar con apply mas el nombre de la
propiedad config como sufijo en CamelCase.
El método update () se ejecuta después de que se haya asignado el valor de la propiedad de configuración. El
nombre del método update debe comenzar con update mas el nombre de la propiedad config como sufijo en
CamelCase. Tiene dos parámetros, newValue y oldValue. Si incluye método apply y update para una
propiedad en particular, primero se aplicará apply y luego se llamará al método uppdate.
Considere el siguiente ejemplo.
Ext.define('Student',{
config:
{
name: 'unnamed',
schoolName : 'Unknown'
},
constructor: function(config){
this.initConfig(config);
},
applyName: function(name){
return Ext.String.capitalize(name);
},
En el ejemplo anterior, hemos definido el método applyName () para la propiedad name en config que pondrá
en mayúsculas el valor de la propiedad name. Se llamará al método applyName () siempre que establezca el
valor de name en config usando el método setName (). Por lo tanto, puede asegurarse de que el valor del name
siempre estará en mayúsculas, incluso si el usuario lo configura en minúsculas.
El método updateName () en el ejemplo anterior se ejecuta después de asignar el valor de la propiedad config
y por eso incluye dos parámetros. El primer parámetro es para el nuevo valor y el segundo parámetro es para
el valor antiguo.
Ext.define('Student', {
config: {
name: ''
},
mixins:
{
observable: 'Ext.util.Observable'
},
constructor: function(config){
this.mixins.observable.constructor.call(this, config);
},
updateName: function(newValue, oldValue){
this.fireEvent('studentNameChanged', newValue);
}
});
newStudent.on('studentNameChanged', function(name){
alert('El nombre del estudiante ' + name + 'fue modificado.');
});
newStudent.setName('John');
En el ejemplo anterior, hemos incluido Ext.mixin.Observable mixin usando mixins config para que podamos
usarlo. En el constructor, llamamos this.mixins.observable.constructor.call (this, config) que inicializa la
configuración. En el método updateName (), activamos el evento personalizado StudentNameChanged
utilizando el método fireEvent () con un nuevo valor. Manejamos este evento en la instancia de newStudent
donde registramos el controlador usando el método on ().
Cada componente en Ext JS incluye la cantidad de eventos que podemos manejar en ViewController o en el
propio componente. Aprenda sobre el evento de componentes en la sección de componentes.
Ext.dom.Element
Ext JS incluye la clase Ext.dom.Element que envuelve el elemento HTML DOM real. La clase Ext.dom.Element
incluye métodos para modificar el elemento DOM y también gestiona los problemas en varios navegadores.
El método Ext.get () y Ext.fly () devuelve un objeto de Ext.dom.Element.
Method Description
Ext.get() Devuelve un objeto de Ext.dom.Element para el id específico del elemento DOM existente.
Ext.fly() Realiza la misma acción que Ext.get (). Está diseñado para manipular el elemento DOM como una sola
declaración y no almacena una referencia en memoria.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script src="../../ext-4.2.1/ext-4.2.1.883/ext-debug.js"></script>
<script>
Ext.onReady(function () {
// obtiene el objetp Ext.dom.Element
var txtFirst = Ext.get("txtFirstName");
txtFirst.set({ 'value': 'Steve' });
console.log(txtFirst.$className);
});
</script>
</head>
<body>
Nombre: <input type="text" id="txtFirstName" class="myclass"/> <br /><br />
Apellido: <input type="text" id="txtLastName" class="myclass" />
</body>
</html>
En el ejemplo anterior, el método Ext.get () devuelve un objeto Ext.dom.Element para el tipo de entrada cuya
id es "txtFirstName". Luego puede usar varios métodos Ext.dom.Element para manipular el elemento DOM,
por ejemplo, el método set() se usa en el ejemplo anterior para establecer el valor de entrada. De la misma
manera, el método Ext.fly() se usa para obtener la referencia del elemento DOM y manipularlo en la misma
declaración.
Nota: cuando no necesita realizar varias operaciones en el elemento DOM, la función Ext.fly() es la forma
más eficiente de manipular un elemento DOM. Está diseñado para funcionar de manera más eficiente y
utiliza menos memoria.
El siguiente ejemplo muestra cómo manipular múltiples elementos DOM en una sola llamada de método.
<!DOCTYPE html>
<html xmlns="https://www.w3.org/1999/xhtml">
<head>
<title></title>
<script src="../../ext-4.2.1/ext-4.2.1.883/ext-debug.js"></script>
<script>
Ext.onReady(function () {
// Obtiene todos los elementos de entrada y configura su bgcolor a amarillo
var inputElements = Ext.select("input");
inputElements.set({'style': 'background-color:yellow'});
});
</script>
</head>
<body>
Nombre: <input type="text" id="txtFirstName" class="myclass"/> <br /><br />
Apellido: <input type="text" id="txtLastName" class="myclass" />
</body>
</html>
En el ejemplo anterior, Ext.select() devuelve Ext.dom.CompositeElement que incluye todos los elementos de
entrada. A continuación, puede manipular todos los elementos en una sola declaración. El método set()
establece el atributo de estilo de todos los elementos seleccionados.
De la misma manera, puede seleccionar otros elementos pasando diferentes selectores de CSS al método
select() y usar varios métodos Ext.dom.CompositeElement. Visite sencha docs para conocer todos los métodos
Ext.dom.CompositeElement.
DomHelper:
La clase Ext.dom.Helper nos permite agregar nuevos elementos DOM, modificar o eliminar elementos DOM
existentes en un documento HTML.
La clase DomHelper usa la sintaxis basada en JSON con los siguientes atributos especiales para crear nuevos
elementos DOM.
Atributo Descripción
Id El id del elemento
El siguiente ejemplo muestra cómo crear elementos DOM usando la clase Ext.DomHelper.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script src="../../ext-4.2.1/ext-4.2.1.883/ext-debug.js"></script>
<script>
Ext.onReady(function () {
dh.append("div1", listItems);
});
</script>
</head>
<body>
<div id="div1">
</div>
</body>
</html>
Ext.onReady(function () {
Ext.create('Ext.Component', {
id:'myComponent',
renderTo: Ext.getBody(),
html:'Hola Mundo!'
});
});
Etapa Descripción
Renderización Creando el DOM para el componente y agregándolo a la jerarquía del DOM con los eventos,
CSS, etc..
Componentes UI de Ext JS 6:
Ext JS 6 contiene los siguientes componentes de IU listos para usar.
xtype: Cada componente tiene un nombre simbólico llamado 'xtype'. Por ejemplo, Ext.panel.Panel tiene xtype: 'panel'.
Visite la documentación de Sencha para saber cómo se ve y cómo funciona cada componente.
Contenedores Ext JS:
Ext JS incluye componentes que pueden contener otros componentes que se denominan container. Puede agregar,
insertar o eliminar componentes del container y también organizar componentes secundarios utilizando diferentes
diseños.
Ext.container.Container es una clase base para todos los contenedores en Ext JS.
Añadiendo componentes al contenedor:
Puede agregar diferentes tipos de componentes Ext JS en un contenedor utilizando la configuración de elementos o el
método add().
Nota: El contenedor también puede incluir otro contenedor.
El siguiente ejemplo muestra cómo agregar componentes a un contenedor utilizando elementos config y el método add().
Ext.onReady(function () {
var comp1 = Ext.create('Ext.Component', {
html:'Component 1'
});
Nota: Los contenedores son iguales en Ext JS 4.x, 5.xy 6.x. La única diferencia es que la versión incremental proporciona
más propiedades y métodos de configuración.
Contenedores Ext JS 6:
La siguiente tabla enumera todos los contenedores importantes en Ext JS 6.
Ext.form.FieldContainer fieldcontainer FieldContainer implementa mixins que se pueden etiquetar para que se
puedan representar con una etiqueta y un mensaje de error en cada
componente sub-elemento. Puede utilizar fieldcontainer en el
formulario para organizar los campos internos.
Ext.grid.Panel grid Grid muestra una gran cantidad de datos tabulares con clasificación,
filtrado y otras funciones.
Nombre de la Clase xtype Descripción
layout: 'auto'
//o
layout: {
type: 'auto'
}
Layout/diseño Descripción
Absolute Este diseño hereda el diseño de anclaje y agrega la capacidad de posicionar el componente en
coordenadas particulares utilizando las opciones de configuración estándar de x, y.
Accordion Este diseño gestiona múltiples paneles en un estilo de acordeón expandible. Por defecto, un panel
puede expandirse en cualquier momento dado, pero también puede expandir múltiples paneles
usando la configuración múltiple.
Anchor Este diseño permite el anclaje de elementos contenidos en relación con las dimensiones del
contenedor. Por favor, visite Anchor Rules.
Auto Este diseño es aplicable cuando no se configura ningún diseño en un contenedor. AutoLayout
proporciona solo una transferencia de las llamadas de diseño a los contenedores secundarios.
Border Este es un estilo de diseño de interfaz de usuario orientado a la aplicación de múltiples paneles que
admite múltiples paneles anidados, barras automáticas entre regiones y la expansión y el colapso
integrados de las regiones.
Card Este diseño gestiona múltiples componentes secundarios, cada uno de ellos instalado en el
contenedor, donde solo un único componente secundario puede ser visible en un momento dado.
Este estilo de diseño se usa más comúnmente para los asistentes y las implementaciones de
pestañas.
Fit Este diseño se utiliza en un contenedor que contiene un solo elemento que se expande
automáticamente para llenar el contenedor.
Layout/diseño Descripción
Form Este es un diseño que representará campos de formulario, uno debajo del otro, todo estirado hasta
el ancho del contenedor.
HBox Un diseño que organiza los elementos horizontalmente a través de un contenedor. Align, Flex y
Pack son importantes opciones de configuración para este diseño.
Table Este diseño le permite representar fácilmente el contenido en una tabla HTML.
VBox Un diseño que organiza los elementos verticalmente en un contenedor. Align, Flex y Pack son
importantes opciones de configuración para este diseño.
Ext.create('Ext.container.Container', {
style: {borderColor: 'Red', borderStyle: 'solid', borderWidth: '1px'},
renderTo: Ext.getBody(),
padding: '5 5 5 5',
layout: {type: 'hbox'},
items: [comp1, comp2, container]
});
});
</script>
</body>
</html>
Visite Layouts Example para obtener más información práctica sobre diseños.
ComponentQuery:
Ext JS proporciona la clase Singleton Ext.ComponentQuery para buscar componentes en la página HTML con
una sintaxis similar a un selector CSS.
La clase Ext.ComponentQuery proporciona diferentes métodos para realizar diferentes tareas. Por ejemplo,
agregar propiedades en una clase componente, crear un objeto de un componente, obtener propiedades de
configuración de un componente, consultar componentes de búsqueda, etc.
Los componentes se pueden recuperar de las siguientes maneras.
Query Type Descripción
itemId or id Los componentes pueden ser recuperados por su id o itemId. La identificación debe tener el prefijo #.
Attributes Los componentes pueden ser recuperados por sus atributos o propiedades config.
Direct child Los componentes pueden ser recuperados por la relación hijo directo.
Parent Ext.ComponentQuery.query('textfield ^ panel'); // Recupera todos los paneles que sean padre de un
textfield.
Ext.create('Ext.container.Container', {
id:'myContainer',
renderTo: Ext.getBody(),
padding: '5 5 5 5',
layout: { type: 'vbox' },
items: [
{
xtype: 'textfield',
fieldLabel:'Nombre'
},
{
xtype: 'textfield',
fieldLabel: 'Apellido'
},
{
xtype: 'panel',
layout:'vbox',
items: [
{
xtype: 'datefield',
fieldLabel: 'Fech de Nac.'
},
{
xtype: 'container',
items: [
{
xtype: 'textfield',
fieldLabel: 'email',
itemId:'email'
}
]
}
]
}
});
En el ejemplo anterior, la primera consulta 'container datafield' busca todos los componentes del campo de
fecha dentro de cualquier contenedor en un documento.
La segunda consulta 'panel> datafield' busca todos los campos de fecha que son hijos directos del panel.
La tercera consulta '#myContainer #email' busca el componente cuya id es 'email' dentro de un contenedor
cuya id es 'myContainer'.
Consulte la documentación de Sencha para obtener más información sobre Ext.ComponentQuery.
Ext JS Viewport:
Viewport en Ext JS es un contenedor especializado que representa el área de aplicación visible en el navegador.
Solo puede haber una ventana gráfica en la aplicación de una sola página ExtJS 4.
El Viewport representa al cuerpo del documento y se redimensiona automáticamente al tamaño de la ventana
del navegador y administra el cambio de tamaño de la ventana.
Vamos a crear una ventana gráfica en una aplicación Ext JS.
Primero, crea una app.js como se muestra a continuación.
Ext.application({
name: 'School',
mainView: 'School.view.Viewport'
});
En el archivo app.js anterior, config del mainView indica la vista inicial que se debe representar. Aquí, es una
vista de clase School.view.Viewport. Usaremos el kit de herramientas clásico para nuestra aplicación de
muestra. Entonces, crea una carpeta classic y una carpeta view dentro de la carpeta classic.
En la carpeta view, cree Viewport.js y defina la clase Schoo.view.Viewport como se muestra a continuación.
Ext.define('School.view.Viewport', {
extend: 'Ext.container.Viewport',
alias: 'widget.StudentViewport',
requires: ['Ext.menu.Menu','School.view.ViewportController'],
controller:'viewport',
config: {},
constructor: function(config) {
return this.callParent(arguments);
},
initComponent: function) {
Ext.apply(this, {
id: 'StudentViewportID',
title: 'Student Information',
layout: {
type: 'border'
},
items: [{
region: 'north',
border: false,
margins: '0 0 5 0',
items: [{
xtype: 'container',
html: '<h1 class="x-panel-header">extjs-tutorial.com</h1>'
}, {
xtype: 'toolbar',
itemId: 'schoolToolbar',
enableOverflow: true,
items: [{
xtype: 'button',
// por defecto para las barras de herramientas-toolbars
text: 'Add Tab',
itemId: 'btnAddtabs',
listeners: {
click: 'onAddTab'
}
}, {
xtype: 'button',
// por defecto para las barras de herramientas
text: 'Add Window',
itemId: 'btnAddwindow',
listeners: {
click: 'onAddWindow'
}
}, {
xtype: 'splitbutton',
text: 'Split Button'
},
'->',
{
xtype: 'textfield',
name: 'field1',
emptyText: 'enter search term'
},
'-',
'text 1',
{
xtype: 'tbspacer'
},
'text 2', {
xtype: 'tbspacer',
width: 50
},
'text 3']
}]
}, {
region: 'west',
collapsible: true,
title: 'Navigation',
width: 150,
split: true,
items: [{
xtype: 'menu',
width: 150,
plain: true,
floating: false,
showSeparator: true,
items: [{
text: 'Menu item 1'
}, {
xtype: 'menuseparator'
}, {
text: 'Menu item 2'
}, {
xtype: 'menuseparator'
}, {
text: 'Menu item 3'
}]
}]
}, {
region: 'south',
title: 'South Panel',
collapsible: true,
html: 'Aqui ira información',
split: true,
height: 100,
minHeight: 100
}, {
region: 'east',
title: 'Panel Este',
split: true,
width: 150
}, {
region: 'center',
xtype: 'tabpanel',
activeTab: 0,
items: [{
title: 'Default Tab',
html: 'El contenido de la primera pestaña. Otros pueden ser agregados dinámicamente '
}, {
title: 'Segundo Tab',
html: ' El contenido de la segunda pestaña. Otros pueden ser agregados dinámicame
nte. '
}]
}]
});
this.callParent(arguments);
}
});
En la clase Viewport anterior, incluye diferentes regiones para separar diferentes secciones de la vista de la
aplicación, como encabezado, barra izquierda, barra derecha, área central y área de pie de página.
Ext.container.Panel es el xtype predeterminado en la colección de elementos de Viewport.
Ahora, para manejar los eventos de la clase viewport anterior, agregue la clase ViewportController. Para eso,
cree la aplicación -> view -> ViewportController.js y defina la clase School.view.ViewportController como se
muestra a continuación.
Ext.define('School.view.ViewportController', {
extend: 'Ext.app.ViewController',
alias: 'controller.viewport',
onAddTab: function(choice) {
Ext.Msg.alert('Agregar Tab', 'Agrega un nuevo tab aquí.');
}
});
MessageBox:
Puede visualizar muchos tipos de cuadros de mensajes en Ext JS. Ext.window.MessageBox es la clase principal
para crear un cuadro de mensaje en Ext JS.
Ext.MessageBox o Ext.Msg es una instancia única de Ext.window.MessageBox. No es necesario crear un objeto
Ext.window.MessageBox para mostrar el cuadro de mensaje todo el tiempo.
A diferencia de una alerta de JavaScript normal (que detiene la ejecución del navegador), mostrar un cuadro
de mensaje con Ext.Msg no hará que el código se detenga. Si tiene un código que debe ejecutarse después de
la acción del usuario desde el cuadro de mensaje, debe especificar una función de devolución de llamada.
Puede mostrar cuatro tipos de cuadros de mensaje:
Alerta-Alert: muestra un cuadro de mensaje de solo lectura estándar con un botón Aceptar.
Confirmar-Confirm: muestra un cuadro de mensaje de confirmación con los botones Sí y No.
Solicitud-Prompt: muestra un cuadro de mensaje con los botones Aceptar y Cancelar que le solicitan al usuario
ingresar algún texto (similar a la solicitud de JavaScript). Puede ser un cuadro de texto de una sola línea o de
varias líneas.
Personalizado-Custom: estilo de cuadro de mensaje personalizado.
Singleton Alert:
Puede mostrar la alerta usando 'Ext.Msg', que es una forma corta de la clase singleton 'Ext.MessageBox'.
Ext.Msg.alert('Estado', 'Este es un cuadro de mensaje en Ext JS.');
Nota: Si tiene dos mensajes de alerta consecutivos usando 'Ext.Msg', entonces se mostrará el último mensaje
de alerta porque Ext.Msg es una clase singleton.
Ext.Msg.alert('Estado', 'Este es el primer cuadro de mensaje Ext JS.');
En el ejemplo anterior, verá solo un cuadro de mensaje con el mensaje 'Este es el segundo cuadro de mensaje
Ext JS'.
También puede crear un objeto de Ext.window.MessageBox y llamar al método de alerta como se muestra a
continuación:
var msg = Ext.create('Ext.window.MessageBox');
Confirm:
El cuadro de mensaje de confirmación (confirm) muestra el mensaje con los botones Sí y No. También puede
capturar usuarios haciendo clic en el evento para un proceso posterior.
Ext.Msg.confirm("Confirmación", "Desea cuardar los cambios?", function(btnText){
if(btnText === "no"){
Ext.Msg.alert("Alerta", " Has confirmado 'No'.");
}
else if(btnText === "yes"){
Ext.Msg.alert("Alerta", " Has confirmado 'Si'.");
}
}, this);
Prompt:
El indicador muestra un cuadro de mensaje con los botones Aceptar y Cancelar que le solicitan al usuario
ingresar algún texto.
Ext.Msg.prompt("Tutorial Ext JS", "Ingrese su Sencha Id:", function(btnText, sInput){
if(btnText === 'ok'){
Ext.Msg.alert("Status", "Ingresó:" + sInput);
}
}, this);
También puede usar Ext.MessageBox para mostrar la barra de progreso automático de la siguiente manera:
Ext.MessageBox.show({
msg: 'Guardando Cambios, espere...',
progressText: 'Guardando...',
width: 300,
wait: true,
waitConfig:
{
duration: 10000,
increment: 15,
text: 'Guardando...',
scope: this,
fn: function(){
Ext.MessageBox.hide();
Ext.Msg.alert('Estado', 'Guardad exitosamente!');
}
}
});
Visite la documentación de Sencha para obtener más información sobre la barra de progreso.
AVANZADO
Según la figura anterior, la clase model incluye un proxy que obtiene el registro único del servidor para
mostrarlo en la vista Form Ext JS. De la misma manera, el Store incluye el model y el proxy para obtener la
colección de registros del servidor remoto para mostrarlos en la Grid view. Tenga en cuenta que el proxy puede
asociarse con la clase model o la clase store.
Model:
La clase Ext.data.Model define la forma de los datos. Una definición model incluye campos, validaciones y
métodos. Es M en la arquitectura MVC y MVVM .
La clase model debe crearse en la carpeta Model. Por ejemplo, para definir la clase de model Student, cree
Student.js en la carpeta app -> model en Ext JS 6 como se muestra a continuación.
La clase model debe derivarse de la clase Ext.data.Model. La siguiente es una clase model student con
diferentes campos.
Ext.define('Student', {
extend: 'Ext.data.Model',
idProperty:'Id',
fields: [
{name: 'Id', type: 'int'},
'firstName',
'lastName'
]
});
La clase de model Student anterior amplía Ext.data.Model. Define 3 campos: ID, (first name) nombre y (last
name) apellido utilizando la configuración de "fields". Especifique el tipo de un campo usando la propiedad
type de un campo. Si no especifica el tipo, entonces el tipo predeterminado sería string. Ext JS admite
diferentes tipos de campo, como auto, int, string, float, boolean y date.
El siguiente ejemplo muestra el modelo student con validaciones.
Ext.define('Student', {
extend: 'Ext.data.Model',
idProperty:'Id',
fields: [
{name: 'Id', type: 'int'},
'firstName',
'lastName'
],
validators: {
firstName: 'presence',
lastName: {type: 'length', min: 2}
}
});
En el ejemplo anterior, hemos definido la clase model Student con los campos Id, firstName y lastName. La
configuración 'validators' define validaciones para campos.
Puede crear un registro creando un objeto de modelo student y especificar los valores de los campos. El
método isValid() determina si un registro satisface todos los validadores o no, como se muestra a continuación.
var studentRecord = Ext.create('Student',{
firstName:'',
lastName: 'J'
});
if (!studentRecord.isValid())
{
var validation = studentRecord.getValidation();
console.log('Nombre: ' + validation.get('firstName'));
console.log('Apellido: ' + validation.get('lastName'));
}
Ahora, el tipo de campo anterior se puede utilizar con cualquier modelo como se muestra a continuación.
Ext.define('Student', {
extend: 'Ext.data.Model',
idProperty:'Id',
fields: [
{name: 'Id', type: 'int'},
'firstName',
'lastName',
{name:'gender', type:'gender'} // usa el campo personalizado
]
});
var studentRecord = Ext.create('Student',{
firstName:'James',
lastName: 'Bond',
gender:'TEST'
});
if (!studentRecord.isValid())
{
var validation = studentRecord.getValidation();
Uno a uno:
El siguiente ejemplo muestra cómo definir una relación uno a uno entre dos modelos.
Ext.define('Address', {
extend: 'Ext.data.Model',
fields: [
{ name: 'addressId', type: 'int' },
'address',
'city',
'state'
],
identifier: {
type: 'negative'
}
});
Ext.define('Student', {
extend: 'Ext.data.Model',
idProperty:'Id',
fields: [
{ name: 'Id', type: 'int' },
'firstName',
'lastName',
{ name:'addressId', reference:'Address', unique: true}
],
identifier: {
type: 'negative'
}
});
studentRecord.address = address;
En el ejemplo anterior, el modelo Student incluye un campo 'addressId' archivado con la referencia de
'Address' y lo configura como único. Esto hace la relación uno a uno entre el modelo estudiante y dirección.
Uno a muchos:
Hay dos formas de definir relaciones de uno a muchos en Ext JS, usando la configuración hasMany de Ext JS 4
o la nueva configuración de referencia.
El siguiente ejemplo muestra cómo definir una relación de uno a muchos usando la configuración hasMany.
Ext.define('Student', {
extend: 'Ext.data.Model',
idProperty:'Id',
fields: [
{name: 'Id', type: 'int'},
'firstName',
'lastName'
],
identifier: {
type: 'negative'
},
hasMany: {
name: 'Courses',
model:'Course'
}
});
Ext.define('Course', {
extend: 'Ext.data.Model',
idProperty: 'Id',
fields: [
{name: 'Id', type: 'int'},
'courseName'
],
identifier: {
type: 'negative'
}
});
Muchos a muchos:
Ext JS proporciona una manera fácil de definir relaciones de muchos a muchos entre modelos que utilizan la
configuración manyToMany.
Ext.define('Student', {
extend: 'Ext.data.Model',
idProperty:'Id',
fields: [
{ name: 'Id', type: 'int' },
'firstName',
'lastName'
],
identifier: {
type: 'negative'
},
manyToMany: 'Course'
});
Ext.define('Course', {
extend: 'Ext.data.Model',
idProperty: 'Id',
fields: [
{ name: 'Id', type: 'int' },
'courseName'
],
identifier: {
type: 'negative'
}
});
Ext JS ViewModel:
En la sección anterior, aprendiste sobre el modelo. El modelo juega un papel importante en la arquitectura
MVC. Ext JS admite la arquitectura MVVM (Model-View-ViewModel) ya que Ext JS 5 y ViewModel es una
parte importante de la arquitectura MVVM.
ViewModel es una clase que administra datos para un componente de IU específico. Puede pensarlo como
un contenedor de un registro para la vista específica. Admite el enlace de datos bidireccional con el
componente UI, por lo que, tan pronto como el usuario cambia los datos en la vista (view), tiene una copia
más reciente. A diferencia del modelo, no puede incluir proxy, por lo que no puede obtener datos
directamente del servidor remoto.
Vamos a crear un ViewModel simple con datos ficticios y vincularlo a un componente. Considere el siguiente
ejemplo.
Ext.define('MyApp.view.TestViewModel', {
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.test',
data: {
id: 1,
name: 'Steve'
}
});
Ext.create('Ext.Component', {
viewModel:{
type:'test'
},
bind:{
html:'{id} - {name}'
},
renderTo:Ext.getBody()
});
En el ejemplo anterior, hemos creado una clase simple ViewModel llamada MyApp.view.TestViewModel y
extendida de Ext.app.ViewModel. La configuración de alias se utiliza para darle un nombre corto para que
podamos referenciar con este nombre corto en la interfaz de usuario. La configuración (config) de datos (data)
se utiliza para proporcionar un objeto de datos test. Aquí, hemos proporcionado un objeto simple con
propiedades id y name. Se hace referencia a la clase viewmodel en un componente usando config viewModel
con el tipo de viewmodel. Use config bind para vincular el valor específico de la configuración de la interfaz de
usuario con los datos de ViewModel. En el ejemplo anterior, la propiedad html del componente se enlaza con
la propiedad id y name del objeto de datos del viewmodel "test". Use llaves para unir una propiedad particular
como '{id}' o '{name}'. Así que ahora, el componente anterior mostrará "1 - Steve".
data: {
firstName: 'James',
lastName:'Bond'
},
formulas: {
fullName: function(get){
return get('firstName') + ' ' + get('lastName');
}
}
});
En el ejemplo anterior, hemos creado una clase StudentViewModel que extiende de la clase
Ext.app.ViewModel. La configuración de alias asigna un nombre, por lo que podemos referirnos a ella
utilizando un alias en lugar del nombre completo de la clase. La configuración (config) de datos (data) se utiliza
para asignar datos arbitrarios como un objeto. Hemos especificado dos propiedades, firstName y lastName.
ViewModel se puede asociar con uno o más componentes de UI. Podemos usar la propiedad de configuración
de enlace bind para enlazar datos entre el ViewModel y el componente.
El siguiente componente del form vincula las propiedades firstName y lastName del StudentViewModel
anterior con los campos de texto (textfields).
Ext.application({
name: 'SchoolApp',
requires: ['SchoolApp.StudentViewModel'],
launch: function() {
Ext.create('Ext.container.Viewport', {
items: [{
xtype: 'form',
layout:'form',
bodyPadding: '5',
buttonAlign: 'center',
viewModel: {
type: 'StudentViewModel'
},
items: [{
xtype: 'textfield',
fieldLabel: 'Nombre',
bind: {
value: '{firstName}'
}
}, {
xtype: 'textfield',
fieldLabel: 'Apellido',
bind: {
value: '{lastName}'
}
}, {
xtype: 'displayfield',
fieldLabel: 'Nombre Completo',
bind: {
value: '{fullName}'
}
}],
buttons: [{
text: 'Guardar'
}, {
text: 'Cancelar'
}]
}]
})
}
});
Links:
ViewModel incluye la configuración de enlaces links que le da un nombre a un registro específico.
Por ejemplo, la siguiente configuración de enlaces links se usa para dar un nombre a un registro de Estudiante
cuya identificación es 5.
Ext.define('SchoolApp.view.student.StudentViewModel', {
extend: 'Ext.app.ViewModel',
alias:'viewmodel.StudentViewModel',
formulas: {
fullName: function(get){
return get('theStudent.firstName') + ' ' + get('theStudent.lastName');
}
},
links: {
theStudent: {
type: 'Student',
id:5
}
}
});
ViewModel carga el registro de la clase de modelo fuente-Estudiante configurada en este caso. theStudent usa
la clase de modelo de Student para obtener el registro del servidor remoto.
model\Student.js
Ext.define('SchoolApp.model.Student', {
extend: 'Ext.data.Model',
idProperty: 'Id',
schema: {
namespace: 'SchoolApp.model',
proxy: {
type:'ajax',
api: {
read: '/ExampleService.svc/students/'
},
reader:{
type:'json',
rootProperty:'data'
}
}
},
fields: [
{ name: 'Id', type: 'int' },
{ name: 'firstName', type: 'string' },
{ name: 'middleName', type: 'string' },
{ name: 'lastName', type: 'string' },
{ name: 'birthDate', type: 'date' },
{ name: 'address1', type: 'string' },
{ name: 'address2', type: 'string' },
{ name: 'city', type: 'string' },
{ name: 'state', type: 'string' }
]
});
Stores:
ViewModel incluye config de Stores que definen un nuevo store o un store encadenado.
El siguiente ejemplo demuestra la definición de store en el ViewModel.
Ext.define('SchoolApp.view.student.StudentViewModel', {
extend: 'Ext.app.ViewModel',
alias:'viewmodel.StudentViewModel',
formulas: {
fullName: function(get){
return get('firstName') + ' ' + get('lastName');
}
},
stores: {
students: {
model: 'Student',
autoLoad: true,
sorters: [{
property: 'firstName',
direction:'DESC'
}]
}
}
});
En el ejemplo anterior, el store "students" se puede usar para enlazar a un componente del grid.
ViewController:
El controlador (Ext.app.Controller) en ExtJS 4.x se usa para manejar eventos de múltiples componentes
utilizando selectores similares a CSS para hacer coincidir los componentes y responder a sus eventos.
El ViewController (Ext.app.ViewController) se introdujo desde Ext JS 5. ViewController está asociado con un
componente específico de la interfaz de usuario y maneja los eventos provocados por ese componente en
particular sin usar refs (como en Ext JS 4).
ViewController se puede crear en un archivo JS separado en la misma carpeta donde se encuentra el view. Por
ejemplo, StudentViewController para la vista StudentMaster debe crearse en la carpeta app -> view -> de
students.
El siguiente ejemplo muestra StudentViewController que maneja los eventos del componente StudentMaster.
Ext.define('SchoolApp.view.student.StudentViewController', {
extend: 'Ext.app.ViewController',
alias: 'controller.StudentViewController',
},
onReadClick: function () {
this.lookupReference('firstName').setValue('Steve');
this.lookupReference('lastName').setValue('Jobs');
onSaveClick: function () {
Ext.Msg.alert('Status', 'Save button clicked.');
},
onResetClick: function () {
this.lookupReference('firstName').setValue('');
this.lookupReference('lastName').setValue('');
onExitClick: function () {
Ext.Msg.alert('Status', 'Exit button clicked.');
this.getView().destroy();
}
});
config: {},
requires: ['SchoolApp.view.student.StudentViewController'],
title: 'Información del Estudiante',
controller: 'StudentViewController',
initComponent: function () {
Ext.apply(this, {
resizable: false,
collapsible: true,
bodyPadding: '5',
buttonAlign: 'center',
border: false,
layout: 'anchor',
defaults: {
anchor: '100%'
},
items: [{
xtype: 'textfield',
fieldLabel: 'First Name',
reference: 'firstName'
},
{
xtype: 'textfield',
fieldLabel: 'Last Name',
reference: 'lastName'
}
],
buttons: [{
text: 'Read', itemID: 'btnRead',
listeners: {
click: 'onReadClick'
}
},
{
text: 'Save', itemID: 'btnSave',
listeners: {
click: 'onSaveClick'
}
},
{
text: 'Reset',
listeners: {
click: 'onResetClick'
}
},
{
text: 'Exit',
listeners: {
click: 'onExitClick'
}
}
});
this.callParent(arguments);
}
});
En el ejemplo anterior de StudentMaster, StudentMaster incluye la configuración del controlador que apunta
a ViewController. Aquí, StudentViewController manejará todos los eventos generados desde la vista
StudentMaster. Además, la configuración de listeners se usa para especificar el nombre del evento y el nombre
de la función del controlador que se definirá en la clase StudentViewController. Por ejemplo, el evento clic del
botón “Read” será manejado por el método onReadClick definido en StudentViewController.
La configuración de referencia se aplica con los textfields FirstName y LastName para que podamos obtener la
referencia de los textfields FirstName y LastName en StudentViewController para trabajar en ella.
Por lo tanto, es fácil vincular eventos y también obtener la referencia de cualquier componente de la interfaz
de usuario utilizando la configuración reference en ViewController.
},
failure: function (response) {
Ext.Msg.alert('Estado', 'Solicitud fallida.');
}
});
En el ejemplo anterior, enviamos una solicitud HTTP GET al punto final api REST url
http://localhost/api/students utilizando el método Ext.Ajax.request(). La configuración url especifica el punto
final. El método config especifica el método HTTP. Puede ser GET, POST, PUT, DELETE u otro método HTTP
válido. La configuración params especifica el parámetro que debe ir junto con la solicitud HTTP. La
configuración success y failure se utiliza para especificar la función callback que se ejecutará si la solicitud se
ejecuta correctamente o no.
Visite Ext.data.Connection y Ext.Ajax para más información.
Session:
Ext JS 5 introdujo Ext.data.Session. La sesión puede asociarse con cualquier componente de UI, ViewModel o
Store. Administra los datos y maneja la operación CRUD, una vez que se cargan los datos.
Apply session: true config a cualquier componente de la interfaz de usuario para crear una nueva sesión y
adjuntarla. Todos los componentes secundarios pueden generarse a partir de la sesión principal actual.
Veamos un ejemplo de cómo una sesión administra los datos de dos stores y realiza la operación CRUD.
Construiremos UI con dos grids editables, students y states como se muestra a continuación. Crearemos una
sesión y la usaremos para administrar la operación CRUD para ambos grids.
Primero, cree una ventana gráfica como se muestra a continuación.
Ext.application({
name: 'SchoolApp',
autoCreateViewport: false,
views: ['SchoolApp.view.student.StudentList', 'SchoolApp.view.student.StateList'],
requires: ['SchoolApp.view.student.StudentViewModel'],
launch: function () {
Ext.create('Ext.container.Viewport', {
layout: 'border',
dock: 'top',
viewModel: {
type: 'StudentViewModel'
},
session: true,
items: [
{
region: 'north',
xtype: 'toolbar',
items: [{
text: 'Guardar lote',
handler: function () {
try {
var viewport = this.up().up();
var ses = viewport.getSession();
batch.on({
complete: function () {
Ext.Msg.alert('Estado', 'Datos guardados exitosamente!');
},
exception: function () {
Ext.Msg.alert('Error', 'Ocurrió un error');
}
});
batch.start();
}
catch (ex) {
Ext.Msg.alert('Error', ex.message);
}
}
},
{
text: 'Mostrar Cambios',
handler: function () {
var viewport = this.up().up();
var ses = viewport.getViewModel().getSession();
var changes = ses.getChanges();
if (!changes) {
Ext.Msg.alert('Estado', 'Sin Cambios');
return;
}
Ext.Msg.alert('Estado', changedStateNames);
}
Ext.Msg.alert('Estado', changedStudentNames);
}
}
}]
},
{
region: 'center',
xtype: 'StudentList',
bind: { store: '{students}' },
flex: 1
},
{
xtype: 'StateList',
region: 'south',
bind: { store: '{states}' },
flex: 1
}]
});
}
});
En el ejemplo anterior, adjuntamos StudentViewModel y especificamos session:true. Viewport incluye los grids
StudentList y StateList como ítems hijos.
El siguiente es un StudentViewModel.
Ext.define('SchoolApp.view.student.StudentViewModel', {
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.StudentViewModel',
stores: {
students: {
model: 'SchoolApp.model.Student',
session: true,
autoLoad: true,
sorters: [{
property: 'firstName',
direction:'DESC'
}]
},
states: {
model: 'SchoolApp.model.State',
session: true,
autoLoad: true,
sorters: [{
property: 'name',
direction: 'ASC'
}]
}
}
});
En el StudentViewModel anterior, hemos especificado dos stores, students y states. También hemos
especificado la configuración de sesión para ambos stores. Esta sesión gestionará los datos cargados en stores
students y states.
Use el método de sesión getChanges() para obtener la lista de registros que han cambiado. Utilice el método
getSaveBatch() para realizar la operación CRUD en los registros modificados. El siguiente código muestra cómo
enviar registros modificados al servidor remoto.
try
{
var viewport = this.up().up();
var ses = viewport.getSession();
batch.start();
}
catch (ex) {
Ext.Msg.alert('Error', ex.message);
}
En el ejemplo anterior, obtenemos la referencia del viewport y luego obtenemos la sesión de viewport usando
el método getSession(). El método getSaveBatch() devuelve Ext.data.Batch que puede usarse para realizar una
operación por lotes.
model\State.js
Ext.define('SchoolApp.model.State', {
extend: 'Ext.data.Model',
idProperty: 'Id',
proxy: {
type:'ajax',
api: {
read: '/ExampleService.svc/students/'
},
reader:{
type:'json',
rootProperty:'data'
},
writer: {
allowSingle: false
}
},
fields: [
{ name: 'Id', type: 'int' },
{ name: 'name', type: 'string' }
]
});
Store encadenado:
Ext JS 5 introdujo un nuevo tipo de store llamado store encadenado. Un store encadenado está vinculado a un
store de origen. Los registros provienen del store de origen. Un store encadenado define filters y sorters que
actúan de forma independiente sin tener ningún impacto en el almacén de origen. Sin embargo, los filters y
sorters aplicados en el store de origen también pueden tener un impacto en los store encadenados.
El store encadenado se puede definir en un archivo JS separado, así como en un ViewModel.
Veamos un ejemplo de cómo se puede crear un nuevo store encadenado que no tenga un impacto en el store
de origen.
En nuestro ejemplo, crearemos un store de origen y un store encadenado. También crearemos tres grids
simples que muestran los datos de estos stores. Nuestro ejemplo se verá a continuación.
Primero, cree el store para students que actuará como un store de origen como se muestra a continuación.
Ext.define('SchoolApp.store.Student', {
extend: 'Ext.data.Store',
model: 'SchoolApp.model.Student',
autoLoad: true,
sorters: [{
property: 'firstName',
direction: 'ASC'
}]
});
Ahora, cree un store encadenado llamado 'School App.store.Student Chained Store' en la misma carpeta que
se muestra a continuación.
Ext.define('SchoolApp.store.StudentChainedStore', {
extend: 'Ext.data.ChainedStore',
source:'SchoolApp.store.Student',
sorters: [{
property: 'firstName',
direction: 'desc'
}]
});
En el store encadenado anterior, observe que hemos especificado la configuración "fuente" que es
"SchoolApp.store.Student". Además, hemos especificado un sorter separado en el store encadenado. Ahora,
puede enlazar este store con el grid como de costumbre usando la configuración "store" del grid. Verá que el
grid que se adjunta al store encadenado muestra los datos en orden descendente, mientras que el grid con el
store principal muestra los datos en orden ascendente. Sin embargo, la edición de datos en cualquiera de los
grids afecta a todos los grids.
model\Student.js
Ext.define('SchoolApp.model.Student', {
extend: 'Ext.data.Model',
idProperty: 'Id',
schema: {
namespace: 'SchoolApp.model',
proxy: {
type:'ajax',
api: {
read: '/ExampleService.svc/students/'
},
reader:{
type:'json',
rootProperty:'data'
}
}
},
fields: [
{ name: 'Id', type: 'int' },
{ name: 'firstName', type: 'string' },
{ name: 'middleName', type: 'string' },
{ name: 'lastName', type: 'string' },
{ name: 'birthDate', type: 'date' },
{ name: 'address1', type: 'string' },
{ name: 'address2', type: 'string' },
{ name: 'city', type: 'string' },
{ name: 'state', type: 'string' }
]
});
Crear modelo:
Comencemos con el modelo primero. Cree el archivo Student.js en la carpeta app -> model y cree la clase
School.model.Student como se muestra a continuación.
Ext.define('School.model.Student', {
extend: 'Ext.data.Model',
idProperty:'Id',
schema: {
namespace: 'School.model'
},
fields: [
{ name: 'Id', type: 'int', defaultValue: 0},
{ name: 'firstName', type: 'string' },
{ name: 'middleName', type: 'string' },
{ name: 'lastName', type: 'string' },
{ name: 'birthDate', type: 'date' },
{ name: 'address1', type: 'string' },
{ name: 'address2', type: 'string' },
{ name: 'city', type: 'string' },
{ name: 'state', type: 'string' }
],
validations: [{
type: 'presence',
field: 'firstName'
}]
});
xtype: 'studentForm',
title: 'Student Entry Form',
controller: 'student',
initComponent: function () {
Ext.apply(this,
{
// establezca jsonsubmit a true para la operación CUD usando form.Submit()
jsonSubmit: true,
url: '/api/student',
resizable: false,
collapsible: false,
bodyPadding: '5',
buttonAlign: 'center',
border: false,
trackResetOnLoad: true,
layout:
{
type: 'vbox'
},
fieldDefaults:
{
xtype: 'textfield',
msgTarget: 'side',
labelAlign: 'top',
labelStyle: 'font-weight:bold'
},
defaultType: 'textfield',
items: [{
xtype: 'fieldcontainer',
layout: 'hbox',
defaultType: 'textfield',
width: '100%',
fieldDefaults:
{
labelAlign: 'top',
labelStyle: 'font-weight:bold'
},
items: [{
fieldLabel: 'Id',
name: 'Id',
readOnly: true,
width: 55
},
{
fieldLabel: 'Nombre',
flex: 1,
name: 'firstName',
margin: '0 0 0 5',
allowBlank: false
},
{
name: 'middleName',
width: 150,
margin: '0 0 0 5',
fieldLabel: 'Sobrenombre:'
},
{
fieldLabel: 'Apellido',
flex: 1,
margin: '0 0 0 5',
name: 'lastName'
}]
},
{
xtype: 'datefield',
fieldLabel: 'Fecha de Nac.',
name: 'birthDate'
},
{
xtype: 'textfield',
fieldLabel: 'Dirección',
width: '100%',
name: 'address1'
},
{
xtype: 'textfield',
hideLabel: true,
name: 'address2',
width: '100%',
fieldLabel: 'Dirección 2'
},
{
xtype: 'textfield',
fieldLabel: 'Ciudad',
width: '100%',
name: 'city'
},
{
xtype: 'textfield',
fieldLabel: 'Estado',
width: '100%',
name: 'state'
}
],
buttons: [{
text: 'Crear',
itemId: 'btnCreate',
formBind: true,
handler: 'onCreateClick'
},
{
text: 'Leer',
itemId: 'btnLoad',
handler: 'onReadClick'
},
{
text: 'Editar',
itemId: 'btnUpdate',
formBind: true,
handler: 'onUpdateClick'
},
{
text: 'Borrar',
itemId: 'btnDelete',
formBind: true,
handler: 'onDeleteClick'
},
{
text: 'Revertir',
itemId: 'btnReset',
handler: 'onResetClick'
},
{
text: 'Limpiar',
itemId: 'btnClear',
handler: 'onClearClick'
}]
});
this.callParent(arguments);
},
clearForm: function () {
this.getForm().getFields().each(function (field) {
field.validateOnChange = false;
field.setValue('');
field.resetOriginalValue();
});
}
});
Crear ViewController:
Ahora, agregue la clase ViewController que maneja todos los eventos del view Student anterior. Cree
StudentController.js en la carpeta app -> view -> student como se muestra a continuación.
La clase ViewController de student debe derivar de Ext.app.ViewController. La siguiente es una clase Student
ViewController que maneja todos los eventos del view Student.
Ext.define('School.view.student.StudentController', {
extend: 'Ext.app.ViewController',
alias: 'controller.student',
if (!studentForm.isDirty()) {
Ext.Msg.alert('Status', ' No hay nuevos datos para crear.');
return;
}
else if (!studentForm.isValid()) {
Ext.Msg.alert('Status', 'Datos inválidos.');
return;
}
if (resp.data[0]) {
// addstudent devuelve el modelo student con Id para que podamos volve
r a cargar el modelo en el form para que tenga isDirty false
student.set(resp.data[0]);
studentForm.loadRecord(student);
}
},
failure: function (form, action) {
if (action.failureType === Ext.form.action.Action.CLIENT_INVALID) {
Ext.Msg.alert('CLIENT_INVALID', 'Algo se ha perdido. Por favor revisa
e intenta de nuevo.');
}
if (action.failureType === Ext.form.action.Action.CONNECT_FAILURE) {
Ext.Msg.alert('CONNECT_FAILURE', 'Status: ' + action.response.status +
': ' + action.response.statusText);
}
if (action.failureType === Ext.form.action.Action.SERVER_INVALID) {
Ext.Msg.alert('SERVER_INVALID', action.result.message);
}
}
});
},
if (resp.data.length > 0) {
// addstudent devuelve el modelo student con Id para que podamos v
olver a cargar el modelo en el form para que tenga isDirty false
var student = Ext.create('School.model.Student');
student.set(resp.data[0]);
studentForm.loadRecord(student);
}
}
catch (ex) {
Ext.Msg.alert('Status', 'Exception: ' + ex.Message);
}
},
failure: function (form, action) {
Ext.Msg.alert("Carga fallida", action.result.errorMessage);
}
});
},
if (!studentForm.isDirty()) {
Ext.Msg.alert('Status', 'No hay cambios pendientes para guardar.');
return;
}
else if (!studentForm.isValid()) {
Ext.Msg.alert('Status', 'Datos invalidos.');
return;
}
studentForm.submit({
url: '/api/student',
waitMsg: 'Actualizando..',
method: 'PUT',
headers:
{
'Content-Type': 'application/json'
},
clientValidation: true,
success: function (form, action) {
try {
var student = Ext.create('School.model.Student');
var resp = Ext.decode(action.response.responseText);
if (resp.data.length > 0) {
// addstudent devuelve el modelo student con Id para que podamos v
olver a cargar el modelo en el form para que tenga isDirty false
student.set(resp.data[0]);
studentForm.loadRecord(student);
}
}
},
failure: function (form, action) {
if (action.failureType === Ext.form.action.Action.CLIENT_INVALID) {
Ext.Msg.alert('CLIENT_INVALID', 'Algo se ha perdido. Por favor revisa
e intenta de nuevo.');
}
if (action.failureType === Ext.form.action.Action.CONNECT_FAILURE) {
Ext.Msg.alert('CONNECT_FAILURE', 'Status: ' + action.response.status +
': ' + action.response.statusText);
}
if (action.failureType === Ext.form.action.Action.SERVER_INVALID) {
Ext.Msg.alert('SERVER_INVALID', action.result.message);
}
}
});
},
onDeleteClick: function (sender, record) {
var me = this,
studentForm = me.getView();
student.set(studentForm.getValues());
data = student.getData();
Ext.Msg.show({
title: 'Borrar',
msg: '¿Quieres borrar este registro?',
width: 300,
closable: false,
buttons: Ext.Msg.YESNO,
icon: Ext.Msg.QUESTION,
fn: function (buttonValue, inputText, showConfig) {
if (buttonValue === 'yes') {
studentForm.submit({
url: '/api/student',
method: 'DELETE',
clientValidation: true,
waitMsg: 'Borrando..',
headers:
{
'Content-Type': 'application/json'
},
Ext.Msg.alert('Success', resp.message);
}
catch (ex) {
Ext.Msg.alert('Status', 'Exception: ' + ex.Message);
}
},
failure: function (form, action) {
if (action.failureType === Ext.form.action.Action.CLIENT_INVAL
ID) {
Ext.Msg.alert('CLIENT_INVALID', 'Algo se ha perdido. Por f
avor revisa e intenta de nuevo.');
}
if (action.failureType === Ext.form.action.Action.CONNECT_FAIL
URE) {
Ext.Msg.alert('CONNECT_FAILURE', 'Status: ' + action.respo
nse.status + ': ' + action.response.statusText);
}
if (action.failureType === Ext.form.action.Action.SERVER_INVAL
ID) {
Ext.Msg.alert('SERVER_INVALID', action.result.message);
}
}
});
}
}
});
},
onResetClick: function (sender, record) {
this.getView().getForm().reset();
},
onClearClick: function (sender, record) {
this.getView().clearForm();
},
});
Como puede ver en la clase controladora anterior, lee datos del servidor remoto usando el método form.load
() y realiza la operación CRUD usando el método form.submit (). Llama a api url/api/student para la operación
CRUD. (La url completa de la API Rest es http://localhost/api/student) Para cargar los datos, el método
form.load() envía la solicitud GET a la url /api/student. De la misma manera, form.submit() envía la solicitud
POST para crear un nuevo registro de student, la solicitud PUT para actualizar el registro y la solicitud DELETE
para eliminar el registro. Chequee el handler click de los botones Crear, Actualizar, Eliminar y Leer para saber
más.
Por lo tanto, puede implementar la operación CRUD en el formulario Ext JS. Haga clic en el Ejemplo en vivo a
continuación para ver el código de ejemplo completo en la estructura de carpetas MVVM.
CRUD en Grid Ext JS 6:
Aquí, aprenderá cómo implementar la operación CRUD en Ext JS 6
Creamos nuestra primera aplicación Ext JS 6 en la sección de la aplicación en First Ext JS. Aquí, continuaremos
y agregaremos el view grid para enumerar a todos los estudiantes con los botones Agregar y Eliminar que se
verán a continuación.
Crear modelo:
Comencemos con el modelo primero. Cree el archivo Student.js en la carpeta app -> model y cree la clase
School.model.Student como se muestra a continuación.
Ext.define('School.model.Student', {
extend: 'Ext.data.Model',
idProperty:'Id',
schema: {
namespace: 'School.model'
},
fields: [
{ name: 'Id', type: 'int', defaultValue: 0},
{ name: 'firstName', type: 'string' },
{ name: 'middleName', type: 'string' },
{ name: 'lastName', type: 'string' },
{ name: 'birthDate', type: 'date' },
{ name: 'address1', type: 'string' },
{ name: 'address2', type: 'string' },
{ name: 'city', type: 'string' },
{ name: 'state', type: 'string' }
],
validations: [{
type: 'presence',
field: 'firstName'
}]
});
controller: 'student-list',
viewModel: { type: 'studentviewmodel' },
reference:'studentlistgrid',
selType: 'rowmodel',
selModel:
{
mode: 'SINGLE'
},
viewConfig:
{
stripeRows: true
},
listeners: {
selectionchange: 'onSelectionChange'
},
bind: {
store: '{StudentListStore}'
},
initComponent: function () {
Ext.apply(this,
{
plugins: [Ext.create('Ext.grid.plugin.RowEditing',
{
clicksToEdit: 2
})],
columns: [{
text: "Id",
dataIndex: 'Id',
hidden: false,
width: 35
},
{
text: "Nombre",
flex: 1,
dataIndex: 'firstName',
editor:
{
// por defecto es el textfield si no se proporciona xtype
allowBlank: false
}
},
{
text: "Sobre-nombre",
flex: 1,
dataIndex: 'middleName',
editor:
{
allowBlank: true
}
},
{
text: "Apellido",
flex: 1,
dataIndex: 'lastName',
editor:
{
allowBlank: true
}
},
{
xtype: 'datecolumn',
header: "Fecha Nac.",
width: 135,
dataIndex: 'birthDate',
editor:
{
xtype: 'datefield',
allowBlank: true
},
renderer: Ext.util.Format.dateRenderer('d/m/Y')
},
{
text: "Ciudad",
flex: 1,
dataIndex: 'city',
editor:
{
allowBlank: true
}
},
{
text: "Estado",
flex: 1,
dataIndex: 'state',
editor:
{
allowBlank: true
}
}],
tbar: [{
text: 'Agregar Estudiante',
iconCls: 'fa-plus',
handler: 'onAddClick'
}, {
itemId: 'removeStudent',
text: 'Quitar Estudiante',
iconCls: 'fa-times',
reference: 'btnRemoveStudent',
handler: 'onRemoveClick',
disabled: true
}]
});
this.callParent(arguments);
}
});
El grid anterior, incluye dos configs importantes el controller y el viewModel. La configuración del controller
especifica la clase controller para este grid view que manejará los eventos de esta vista. La configuración de
viewModel especifica la clase ViewModel que incluye el store para este grid.
Crear ViewModel:
Ahora, cree la clase StudentViewModel para el grid de la Lista de estudiantes en la carpeta app -> view ->
student como se muestra a continuación:
}
});
Como puede ver, School.view.student.StudentViewModel incluye un store que estará vinculado al grid view.
Las configuraciones autoSync y autoLoad se configuran como verdaderas en StudentListStore para que el grid
muestre los datos tan pronto como cargue los registros y también actualizará o eliminará los registros una vez
que el usuario los modifique.
Crear ViewController:
Cree StudentViewController.js en la carpeta app -> view -> student.
alias: 'controller.student-list',
studentStore.insert(0,studentModel);
},
studentStore.remove(selectedRows);
},
Por lo tanto, puede implementar CRUD en grid en la arquitectura Ext JS 6 MVVM. Haga clic en el Ejemplo en
vivo a continuación para ver el código de ejemplo completo en la estructura de carpetas MVVM.
Nota: asegúrese de que su servicio acepte una matriz de objetos model como un parámetro de entrada porque
el método de sincronización enviará una matriz de objetos model como una carga útil de solicitud a la url
configurada.
Podemos llamar al método sync() de la misma manera que se vio en el capítulo anterior. Sin embargo, debemos
ser cuidadosos en el manejo de excepciones, como se muestra en el siguiente ejemplo:
// se disparan las solicitudes crear, actualizar y eliminar cuando se realizan sincronizacio
nes y se confirman los cambios en el store cuando autoSync = false
studentStore.sync({
if(batch.hasException){
Según el ejemplo anterior, verificamos si alguna operación ha fallado en un lote y mostramos el número de
operaciones fallidas de creación, actualización y eliminación.
controller\StudentMaster.js
Ext.define('School.controller.StudentMaster',
{
extend : 'Ext.app.Controller',
models : ['School.model.Student'],
stores : ['School.store.Student'],
views: ['School.view.StudentGrid'],
refs : [{
ref : 'studentGrid',
selector : 'viewport StudentGrid'
}],
init : function(){
this.control({
'viewport > StudentGrid button[itemId=btnSave]':
{
click : this.onSaveClick
},
'viewport > StudentGrid button[itemId=btnCreate]':
{
click : this.onCreateClick
},
'viewport > StudentGrid button[itemId=btnDelete]':
{
click : this.onDeleteClick
},
'viewport > StudentGrid button[itemId=btnLoad]' :
{
click : this.onLoadClick
}
});
},
onSaveClick : function(){
if(batch.hasException){
},
onLoadClick : function(){
},
onCreateClick : function(){
var studentGrid = this.getStudentGrid();
var studentStore = studentGrid.getStore();
},
onDeleteClick : function(){
Necesitaríamos crear las siguientes clases para crear una demostración de paginación de cuadrícula como se
muestra arriba.
Model
ViewModel
View
Además, la implementación de la paginación del lado del servidor requiere la API REST u otro servicio web que
maneje la solicitud HTTP con parámetros de página (page), (start) inicio y (limit) límite. Hemos creado la
siguiente API web en .NET que maneja la solicitud HTTP GET.
public class StudentWebAPI
{
public StudentPage GetStudentPage(int page, int start, int limit)
{
currentPage.TotalCount = students.Count;
return currentPage;
}
}
}
public class StudentPage
{
public int TotalCount { get; set; }
Como puede ver en el ejemplo anterior, GetStudentPage manejará la solicitud GET de HTTP con los parametros
page, start y limit y devolverá una parte de los registros según estos parámetros. Enviará la clase StudentPage
como una respuesta que incluye las propiedades TotalCount y Students que se utilizarán para configurar la
paginación en Store ViewModel.
Crear modelo:
En primer lugar, vamos a crear una clase model para student. Cree Student.js en la carpeta app -> model y
defina la clase Student como se muestra a continuación.
Ext.define('School.model.Student', {
extend: 'Ext.data.Model',
idProperty:'Id',
schema: {
namespace: 'School.model'
},
fields: [
{ name: 'Id', type: 'int', defaultValue: 0},
{ name: 'firstName', type: 'string' },
{ name: 'middleName', type: 'string' },
{ name: 'lastName', type: 'string' },
{ name: 'birthDate', type: 'date' },
{ name: 'address1', type: 'string' },
{ name: 'address2', type: 'string' },
{ name: 'city', type: 'string' },
{ name: 'state', type: 'string' }
]
});
Crear ViewModel:
Después de crear la clase model, vamos a crear la clase ViewModel. Cree StudentViewModel.js en la carpeta
app -> view -> student y defina la clase StudentViewModel como se muestra a continuación.
Ext.define('School.view.student.StudentViewModel', {
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.studentviewmodel',
stores: {
StudentListPagingStore: {
model: 'School.model.Student',
autoLoad: true,
pageSize: 5,
proxy:
{
type: 'rest',
url: '/api/student'
reader:
{
type: 'json',
rootProperty: 'Students',
totalProperty: 'TotalCount'
}
}
}
}
});
});
this.callParent(arguments);
}
});
En la grid view anterior, hemos usado pagingtoolbar en la barra inferior. Esta es la barra de herramientas de
paginación que muestra los botones: siguiente, anterior, primero y último con información de paginación.
Puede configurar esto según su necesidad. Visite Sencha docs para obtener más información sobre la barra de
herramientas de paginación.
Por lo tanto, puede implementar la paginación del lado del servidor en el componente Ext JS Grid. Haga clic en
el Ejemplo en vivo a continuación para ver el código de ejemplo completo en la estructura de carpetas MVVM.