Proyecto nuevo
Bueno muchachos, la otra semana comienzo un proyecto desde cero, hay que aclarar que es mi primer proyecto con Extjs y quiero que quede todo documentado acá, desde el planteamiento del problema, hasta por donde empezar, que problemas me surjan, como se solucionan (espero acá recibir una ayudita en eso <!-- s;) --><!-- s;) --> ), no creo que valla muy rápido pero iremos seguros. La idea es que entre todos aprendamos.
Todo el código que se coloque acá podrán utilizarlo en la manera que lo deseen (si alguna vez les sirve).
La otra semana coloco el planteamiento básico del problema, para que empecemos en forma.
Por ahora les adelanto que trabajaremos, con php (manejo del lado del servidor), html, mysql (bases de datos), power designer (para hacer el modelo lógico y físico), dreamweaver (editor), wamp (para hacer las pruebas locales) y por supuesto Extjs 3.0 RC2.
Espero que salga una bonita experiencia de todo esto!!.
Hasta la próxima semana que empecemos con todo esta aventura de aprender!!
Va a resultar interesante,yo tambien estoy en mi primer proyecto con ext y han salido muchas dudas que poco poco he ido resolviendo
Yo tengo ya casí 2 años de experiencia con Ext realizando sistemas empresariales, por ahi les puedo dar algunos tips, también hay otros usuarios que pueden aportar buenas ideas y seguramente enseñarnos cosas que no sabemos.
Excelente iniciativa la tuya <!-- s:D --><!-- s:D --> felicidades
saludos
Hola, tengo casi dos años trabajando con este framework y durante ese transcurso he tenido muchas dificultades que al final se han podido solucionar, espero poder apoyarlos con cualquier duda, solo no olviden postear, saludos.
Jonathan Lara V.
twitter: @jonathanlarav
[url]http://jonathanlarav.blogspot.com/[/url]
muchas Gracias a todos por el apoyo y el ánimo por ayudar!!.. mas tarde empezaré a postear el planteamiento inicial del problema para por fin empezar.. la verdad estoy algo emocionado con todo esto...
Y de nuevo muchas gracias por su disposición a ayudar!! <!-- s:D --><!-- s:D -->
Bueno muchachos, quiero aclarar que la idea la tome de un proyecto que desarrolle cuando estaba a media carrera en la universidad, en ese tiempo lo desarrolle utilizando Java (pero fué hace rato y por lo tanto de muy baja calidad, también tenía menos cosas), ahora quiero desarrollarlo con ayuda de Extjs y haciendo un rediseño completo de toda la parte gráfica, lógica y de bases de datos, en pocas palabras quiero que éste sea un proyecto completo y bien implementado en donde pueda aprender mucho y para eso abusaré un poco de su ayuda
(espero no aburrirlos).
La ídea es la siguiente:
En una universidad se presta el servicio de prestamo de equipos para ayuda audiovisual de los estudiantes y profesores en sus exposiciones. Se necesita implementar el servicio web paraque los estudiantes, profesores y administrativos puedan hacer la reserva de equipos en linea y llevar un control interno de préstamos, estadísticas, gráficas, etc.
algunos requerimientos:
• se maneja el prestamo de equipos (retroproyectores, videobeams, etc), tienen agrupados los equipos, en de video, audio y otros, en la parte de video estan los equipos que sirven para reproducir y visualizar video (televisores, videobeams, reproductores-dvd,etc), en la de audio se encuentran cualquier equipo que sirva para la reproduccion de sonido (grabadoras, micrófonos, parlantes,etc) y lo que no cuadre en estas dos categorías se coloca en "otros". tambien prestan videos en diferentes formatos y salas audiovisuales.
• se necesita tambien manejar unos equipos de reserva (es decir estos nunca se prestan, estan de respaldo por si hay algún incoveniente con otro equipo)
• Se presta el servicio básicamente a estudiantes, profesores, administrativos y egresados. los estudiantes a su vez se dividen en de pregrado, seminarios, cursos para grado, especializaciones y maestrias.
• la información de estudiantes, profesores y administrativos, se encuentran registrados en una base de datos antigua.
• se necesita tambien que se manejen niveles de acceso a las diferentes partes del sistema.
Estadísticas que se deben generar:
• Servicios en general
• Generar la estadística específica por programa académico, por especialización, por diplomado, por seminario.
• Por tipo de Usuario: Postgrados a nivel general, por pregrado, por administrativos, estudiantes y docentes
de pregrado y tecnologías, egresados, otros usuarios.
• Generar la estadística por clase de equipo, video beam, retroproyector, etc.
• Reporte de servicios del día
• Generar la estadística según el rango de fecha requerido.
• Generar estadísticas del préstamo de material por programa (ing. de sitemas, industrial, etc), por tipo de
usuario, etc.
• Generar el gráfico de la estadística solicitada.
• Generar reporte del servicio de las salas audiovisuales
Teniendo en cuenta la información anterior, he decidido tener en cuenta las siguientes entidades en mi diseño del modelo conceptual:
• Bloque
• Salón
• Video
• Formato (formatos de video)
• Tipo de Equipo (si es un equipo de video, sonido u otro)
• Clase de Equipo (esta entidad representa las diferentes clases de equipos que se pueden tener, por ejemplo, televisores, grabadoras, videobeams, proyectores, etc)
• Equipo (entidad que representa un equipo individual, con sus carácterísticas, numero de serie, fecha de compra, clase de equipo, etc)
• Tipo de Usuarios (estudiante, profesor, egresado, administrativo, etc)
• Tipo de Staff (identificará los diferentes tipos de acceso admin, monitor, etc)
• Staff (los diferentes miembros que manejan el sistema)
• Servicio (esta es la entidad donde concurren el resto, es la encargada del registro de una reserva de servicio y la atensión del mismo, debe tener fecha de solicitud= dia que solicita la reserva, fecha del servicio, fecha de finalización del servicio, etc).
Bueno, creo que con esta información queda un poco enmarcado lo que se quiere hacer, más adelante iré colocando requerimientos más específicos de la prestación del servicio.
Ya hice la primera versión del modelo Conceptual, quedó algo así (dar click sobre la figura para verla en tamaño real):
[url=http://www.servidor-imagenes.com/show-image.php?id=900e6509f4f9fad57ae149e2a105ce87][img]http://www.servidor-imagenes.com/thumbnails/db3c73e327303536ec83eef751dff2f4.jpg[/img][/url]
Listo.. por hoy hasta acá.
Siéntanse en la libertad de Criticar lo que sea necesario, de dar su opinión, de darme consejos de los que debo tener en cuenta y no lo he hecho, ustedes tienen mucho más experiencia que yo en esto de desarrollar este tipo de proyectos y tal vez me puedan dar algunos tips a tener en cuenta.
desde ya muchas gracias por sus opiniones, consejos y/o críticas.
Me agrada tu problema es algo que ocurre en muchas universidades y que la mayoría de nosotros conoce.
Solo quisiera hacerte una pregunta. No hubiera sido mejor la ultima version ESTABLE de EXTJS a la versión RC?
Saludos y espero aportar con algo a tu problema
RC es practicamente la que saldra, solo se le hacen pequeños cambios(no siempre) y las ventajas de EXTJS 3.0 sobre la 2.2.1.
Fuera de esto a mi me gustaria algo mas sencillito para empezar <!-- s:P --><!-- s:P -->
Bueno muchachos. ya hice mi base de datos (la dejo adjunta por si la quieren ver), y de acá en adelante solo quiero ir probando poco a poco como ir utilizando formularios, conectando a bases de datos, mejor dicho irme familiarizando con todo este manejo.
Lo primero que debemos hacer es instalar el wamp o Xamp (el que prefieran) personalmente utilizo el wamp, de [url=http://www.wampserver.com/en/download.php]acá[/url] pueden descargar la última versión, éste programa nos permitirá hacer nuestras pruebas localmente, nos instala y configura un servidor local con el apache, mysql, php, etc.
Bueno después de eso descargamos la última versión de Extjs (creo que ya todos saben donde conseguirla <!-- s;) --><!-- s;) --> )
Instalamos el dreamweaver (son libres de escoger cualquier otro editor).
Instalamos una extensión de Dreamweaver que nos permitirá así como cuando escribimos código HTML o CSS en el Dreamweaver y aparece una ventanita mostrándonos el “código” que puede ir con la palabra que estamos escribiendo, esta extensión funciona de la misma forma con el “código” del Extjs. la pueden descargar de [url=http://www.spket.com/dreamweaver-extension.html]esta pagina[/url]
Después de ya tener todo esto listo iniciamos por crear una carpeta en la raiz del sitio (en mi caso C:\wamp\www\"nombre del sitio"), después de haberla creado hacemos dentro de ella otra carpeta (en mi caso le coloque de nombre lib) donde van los archivos que necesitemos de Extjs (por ahora los ingrese todos, ya después me informaré mejor y depuraré esta parte).
Ya teniendo todo esto me dispuse a crear y configurar el nuevo sitio en Dreamweaver, eso lo hago en sitio -> nuevo sitio.. ahí configuro todos los datos de mi sitio nuevo, al terminar ya me queda todo listo para empezar a desarrollar.
lo primero que tienes que hacer es colocar en tu directorio de imágenes una imagen (.gif) transparente de 1x1 que utiliza Extjs, ésta imagen la necesita para realizar correctamente algunas partes gráficas.
Después de hacer todo esto creo que ya estamos listos para iniciar con algo de código.
Bueno, después de tener todo listo, empecé con mi primer formulario, en este caso escogí uno pequeño, el de ingresar bloque ya que son dos campos no más y uno de ellos es un combobox.
lo primero que hice fue incluir todo lo necesario para la utilización del framework:
<link rel="stylesheet" type="text/css" href="lib/resources/css/ext-all.css" /> <script src="lib/adapter/ext/ext-base.js"></script> <script src="lib/ext-all-debug.js"></script> <script src="lib/build/locale/ext-lang-es-min.js"></script>la última inclusión es la que hace que los textos y mensajes automáticos salgan en español y no en ingles (recordar que se esta trabajando con la ultima versión de Extjs, en anteriores versiones el nombre de este archivo cambia), por ejemplo no saldrá el botón con el texto "OK" sino "Aceptar". Empezamos con el cuerpo de nuestro formulario,
<script> Ext.onReady(function(){ Ext.QuickTips.init(); // inicializamos el QuickTips paraque (en este caso) nos muestre un pequeño mensaje de error cuando no se diligencien algunos de los campos de la forma, es una manera elegante de mostrar los mensajes de error Ext.BLANK_IMAGE_URL = 'images/s.gif'; //recuerdan la imagen de 1x1 que les dije que necesitabamos, pues acá le decimos a Ext donde encontrarla var estados = new Ext.data.SimpleStore( //declaramos el Store que nos servirá para el comboBox { fields: ['id', 'estado'], data : [['1','Activo'],['2','Inactivo']] } );Bueno hasta acá hemos declarado todo lo que necesitamos para empezar hacer nuestro pequeño formulario, ahora empezaremos a hacer el formulario:
var Bloque_Form = new Ext.FormPanel({ //empezamos con declarando nuestro panel url: 'ingBloque.php', //pagina a donde será enviada la información del formulario renderTo: document.body, //en donde se va a mostrar nuestro formulario, en este caso será mostrado en el body, si quisieramos mostrarlo dentro de un <div id="ide"></div> tendriamos que colocar el id del div!! //definimos algunas carácterísticas básicas del frame: frame: true, title: 'Bloque Nuevo', width: 250, //declaramos los campos que tendrá nuestro formulario items:[ { xtype: 'textfield', // campo tipo texto fieldLabel: 'Nombre', // el texto que se mostrara al lado del campo name: 'nom', //el nombre con que será enviado allowBlank: false //le decimos que el campo no puede estar vacio al momento de intentar enviar el formulario }, { xtype: 'combo', //campo tipo comboBox name: 'est', // nombre con el que será enviado fieldLabel: 'Estado', //texto que saldrá al lado del combobox mode: 'local', // le decimos que cargará los datos de manera local store: estados, // le decimos el nombre del Store de donde cargará los datos displayField:'estado', //le decimos el campo del Store que mostrara width: 130, triggerAction: 'all', //mostrar siempre todas la opciones del combo valueField : 'id', forceSelection:true, //para que la seleccion no se pierda al perder el foco emptyText:"Seleccione uno", //texto que se mostrará cuando no se ha hecho ninguna selección en el comboBox allowBlank: false //no deje enviar el formulario sino se ha hecho una seleccion } ],ahora agregamos los botones de nuestro formulario:
buttons: [ { text: 'Guardar', //creamos nuestro primer botón handler: function() //declaramos una función anónima que se ejecutará cuando se haga click sobre el botón guardar { Bloque_Form.getForm().submit( // le decimos que envíe el formulario { success: function(f,a) // le decimos que debe hacer si todo lo que se tenía que hacer con el fomulario se hizo, en este caso si se pudo agregar el nuevo bloque, en nuestro caso mostrara un mensaje diciendo bloque agregado con éxito { Ext.Msg.show({ title: 'Agregado', //<- el título del diálogo msg: 'Bloque Agregado Con Exito', //<- El mensaje buttons: Ext.Msg.OK, //<- Botones de Aceptar icon: Ext.Msg.INFO // <- un ícono de Información }); }, failure: function(f,a) //acá le decimos que haga si no se pudo ingresar correctamente el bloque { Ext.Msg.alert('Error', a.result.errormsg); // se carga el mensaje dependiendo de la respuesta del servidor. } } ); } }, { text: 'Limpiar', //boton limpiar, simplemente ejecuta un reset del formulario!! handler: function() { Bloque_Form.getForm().reset(); } } ] }); }); </script> </head>
el código completo quedaría así:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Ayudas Educativas</title> <link rel="stylesheet" type="text/css" href="lib/resources/css/ext-all.css" /> <script src="lib/adapter/ext/ext-base.js"></script> <script src="lib/ext-all-debug.js"></script> <script src="lib/build/locale/ext-lang-es-min.js"></script> <script> Ext.onReady(function(){ Ext.QuickTips.init(); Ext.BLANK_IMAGE_URL = 'images/s.gif'; var estados = new Ext.data.SimpleStore( { fields: ['id', 'estado'], data : [['1','Activo'],['2','Inactivo']] } ); var Bloque_Form = new Ext.FormPanel({ url: 'ingBloque.php', renderTo: document.body, frame: true, title: 'Bloque Nuevo', width: 250, items:[ { xtype: 'textfield', fieldLabel: 'Nombre', name: 'nom', allowBlank: false }, { xtype: 'combo', name: 'est', fieldLabel: 'Estado', mode: 'local', store: estados, displayField:'estado', width: 130, triggerAction: 'all', //mostrar siempre todas la opciones del combo valueField : 'id', selectOnFocus: true, emptyText:"Seleccione uno", forceSelection:true, //para que la seleccion no se pierda al perder el foco allowBlank: false } ], buttons: [ { text: 'Guardar', handler: function() { Bloque_Form.getForm().submit( { success: function(f,a) { Ext.Msg.show({ title: 'Agregado', //<- el título del diálogo msg: 'Bloque Agregado Con Exito', //<- El mensaje buttons: Ext.Msg.OK, //<- Boton de Aceptar icon: Ext.Msg.INFO // <- un ícono de Información }); }, failure: function(f,a) { Ext.Msg.alert('Error', a.result.errormsg); } } ); } }, { text: 'Limpiar', handler: function() { Bloque_Form.getForm().reset(); } } ] }); }); </script> </head> <body> <!-- Nothing in the body --> </body>
ahora miraremos los archivos del lado del sevidor:
lo primero que hice fue crear un archivo que me manejara los datos de conexion, así que cree una carpeta en llamada conexión (donde irán todos los archivos que manejarán las diferentes conexiones a las bases de datos) y dentro de esta carpeta cree un archivo llamado conexión asi:
<?php $host_conexion="localhost"; $database_conexion="nombre de tu base de datos"; $user_conexion="nombre de tu user"; $pass_conexion="clave o password asignado al user"; $conexion=mysql_connect($host_conexion,$user_conexion,$pass_conexion) or die("Error al Conectar la Base de Datos: ". mysql_error() ); //hago la conexión a la base de datos ?>ahora creo el archivo que se encargará de hacer el ingreso del bloque a la base de datos (este archivo está hecho directamente en la raiz del sitio): ingBloque.php:
<?php include ("conexion/conexion.php"); //incluyo el archivo de conexion mysql_select_db($database_conexion,$conexion); // selecciono la base de datos a la que me voy a conectar //recibo los campos que he enviado desde el formulario $nom=$_REQUEST["nom"]; $est=$_REQUEST["est"]; //realizo el ingreso de los datos a la base de datos $result=mysql_query("insert into bloque (BLQ_NOM,BLQ_EST) values ('$nom','$est')"); if($result){ //si fue exitoso da como respuesta: echo "{success: true}"; }else{ //si no fue exitoso, devuelve como respuesta (recuerdan que nuestro formulario cargaba una respuesta desde el servidor, pues errormsg es esa respuesta) echo "{success: false, errormsg: 'Error al ingresar a la Base de datos'}"; } ?>Eso era todo del lado del servidor (por ahora)
Bueno, hasta ahora todo iba bien, pero me he encontrado con un error y es que no me está enviando el " valueField : 'id' " a la base de datos, sino que esta recibiendo el " displayField:'estado' " del comboBox
¿¿Me podrían ayudar en esa parte por favor??
Gracias por su respuesta...
Listo ya encontré la respuesta, era simplemente agregar el campo: hiddenName: 'aca el name del combo', es decir que nuestro código quedaría (la parte del combo):
xtype: 'combo', name: 'est', fieldLabel: 'Estado', mode: 'local', store: estados, displayField:'estado', hiddenName: 'est', width: 130, triggerAction: 'all', //mostrar siempre todas la opciones del combo valueField : 'id', selectOnFocus: true, emptyText:"Seleccione uno", forceSelection:true, //para que la seleccion no se pierda al perder el foco allowBlank: falseYa vamos avanzando.. <!-- s:D --><!-- s:D --> <!-- s;) --><!-- s;) -->
felicidades! si puedes ve poniendo una demo en linea para ir viendo el avance <!-- s:D --><!-- s:D -->
Mi consejo es que no pongas el javascript en el HTML, y que hagas uso del Ext.namespace para evitar problemas en el futuro <!-- s;) --><!-- s;) -->
saludos
Mira te propongo que empaquetemos todas las funcionalidades en un marco de trabajo como este [url]http://foro.quizzpot.com/viewtopic.php?f=6&t=62[/url] , así se organizarían mejor las cosas y a los usuarios les saldrían en el árbol de navegación solo sus funcionalidades y quedaría un poco mejor organizado el trabajo no crees??, solo es una propuesta.
saludos
Bueno como te dije me parece que pudiera quedar así el marco para trabajar adjunto el código para el mismo.
[quote="stock"]felicidades! si puedes ve poniendo una demo en linea para ir viendo el avance <img src="./images/smilies/icon_e_biggrin.gif" alt=":D" title="Very Happy">
Mi consejo es que no pongas el javascript en el HTML, y que hagas uso del Ext.namespace para evitar problemas en el futuro <img src="./images/smilies/icon_e_wink.gif" alt=";)" title="Wink">
saludos[/quote]
Muchas gracias stock, tendré en cuenta tu consejo y la próxima vendrá empaquetado, en cuanto a lo del demo en línea estoy mirando eso, creo que en pocos días lo tendre on-line (eso espero)
[quote="ogonzalezf"]Mira te propongo que empaquetemos todas las funcionalidades en un marco de trabajo como este <a href="http://foro.quizzpot.com/viewtopic.php?f=6&t=62" class="postlink">http://foro.quizzpot.com/viewtopic.php?f=6&t=62</a> , así se organizarían mejor las cosas y a los usuarios les saldrían en el árbol de navegación solo sus funcionalidades y quedaría un poco mejor organizado el trabajo no crees??, solo es una propuesta.
saludos[/quote]
Muchas gracias por tu consejo ogonzalezf, ya descargue tu código y me gusta mucho tu idea.. pero primero tengo que entender bien como funcionaría porque aun no me queda muy claro cómo lo trabajaría.
Muchas gracias a los dos por sus consejos
Amigo creo que en la BD debes de revisar el tema de los identificadores que creo que deben se auto incrementales por ejemplo de la tabla bloque si intentas insertar dos bloques da error por tener llaves duplicadas según lo que tienes en el diseño de tu BD y el ejemplo que acabas de poner. A caso los dejaste así a propósito o en realidad deben de ser auto incrementales.
lo siento.. lo que pasa es que olvide hacerlo con la herramienta de modelación del problema, luego lo cambie directamente en la base de datos, acá te dejo anexo el resultado final de la base de datos.. gracias por tu comentario!! (aunque cabe anotar que está sujeta a cambios que se le daba ir haciendo )
Bueno.. muchachos, después de hacer el primer miniformulario y hacer que funcionará bien.. decidí hacer los otros formularios de ingresar y colocarlos todos dentro de un TabPanel, y luego éste TabPanel colocarlo dentro de una ventana, para dejar todos los formularios en una sola ventana, cave aclarar que están solamente los formularios (mientras aprendo a manejar los diferentes grid <!-- s;) --><!-- s;) --> ).
bueno, lo primero que hice fue quitar el código del html y dejarlo en un archivo .js aparte, aún no lo empaqueto porque no entiendo (aunque gracias a el videotutorial ya se como hacerlo) muy bien como funciona todo esto del empaquetado.. pero apenas lo entienda bien, lo empaqueto de una.
hoy haremos el formulario del Salon, donde necesitaremos cargar en un comboBox desde la base de datos los diferentes bloques que hemos ingresado, mejor dicho aprenderemos a cargar comoboBox con datos desde la Base de Datos.
lo primero que hago es un archivo .php al que llamo "bloques.php" dentro de ese archivo coloco lo siguiente:
<?php include ("conexion/conexion.php"); //incluyo el archivo conexion.php mysql_select_db($database_conexion,$conexion); //selecciono la base de datos a la que me conectaré $result=mysql_query("Select BLQ_IDE, BLQ_NOM from bloque where (BLQ_EST='Act')"); //hacemos la consulta de todos los bloques que tengan su estado como Act (Activo), tenemos en cuenta que solo seleccionamos el campo BLQ_IDE y BLQ_NOM if($result) //si no hubo problemas en la realizacion de la consulta { if (mysql_num_rows($result) > 0) //miramos si recuperó algún valor { while ($obj = mysql_fetch_object($result)) { $arr[] = $obj; //creamos un array con todos los valores recuperados } echo '{success: true, bloques:'.json_encode($arr).'}'; //mostramos la respuesta del servidor.. usamos la función json_encode para transformar el array en una respuesta tipo json (creo que esta incluida desde php 5.2) y agregamos una respuesta de exito, notar que el campo que guarda los datos se llama "bloques" } else //sino se encontró ningún registro echo "{success: false, errormsg: 'No se Encontraron Bloques en la Base de Datos'}"; }else{ //sino no se pudo realizar la consulta echo "{success: false, errormsg: 'Error al Consultar la Base de datos'}"; } ?>así irá quedando nuestro archivo .js, al que nombre "ingresar.js":
Ext.onReady(function(){ Ext.QuickTips.init(); Ext.BLANK_IMAGE_URL = 'images/s.gif'; var estados = new Ext.data.SimpleStore( { fields: ['id', 'estado'], data : [['Act','Activo'],['Inc','Inactivo']] } ); //declaramos el Store para cargar el comboBox desde la Base de Datos var bloques = new Ext.data.Store( { reader: new Ext.data.JsonReader( { fields: ['BLQ_IDE', 'BLQ_NOM'], //estos nos identificas los campos que vendran identificados desde la base de datos root: 'bloques' //acá le decimos cual campo guarda nuestra información en la respuesta (recuerdan que hicimos referencia de él en el archivo .php?) }), proxy: new Ext.data.HttpProxy( { url: 'bloques.php' //le decimos a que archivo conectarse para obtener la respuesta }), autoLoad: true //activamos la opción de autocargado del Store }); var Bloque_Form = new Ext.FormPanel({ url: 'ingBloque.php', //renderTo: document.body, frame: true, title: 'Bloque Nuevo', width: 250, items:[ { xtype: 'textfield', fieldLabel: 'Nombre', name: 'nom_blq', allowBlank: false }, { xtype: 'combo', name: 'est_blq', fieldLabel: 'Estado', mode: 'local', store: estados, displayField:'estado', hiddenName: 'est_blq', width: 130, triggerAction: 'all', //mostrar siempre todas la opciones del combo valueField : 'id', selectOnFocus: true, emptyText:"Seleccione uno", forceSelection:true, //para que la seleccion no se pierda al perder el foco allowBlank: false } ], buttonAlign: 'left', buttons: [ { text: 'Guardar', handler: function() { Bloque_Form.getForm().submit( { success: function(f,a) { Ext.Msg.show({ title: 'Agregado', //<- el título del diálogo msg: 'Bloque Agregado Con Exito', //<- El mensaje buttons: Ext.Msg.OK, //<- Boton de Aceptar icon: Ext.Msg.INFO // <- un ícono de Info }); Bloque_Form.getForm().reset(); }, failure: function(f,a) { Ext.Msg.alert('Error', a.result.errormsg); } } ); } }, { text: 'Limpiar', handler: function() { Bloque_Form.getForm().reset(); } } ] }); //fin del panel //hacemos nuestro formulario para el salon var Salon_Form = new Ext.FormPanel({ url: 'ingSalon.php', //renderTo: document.body, frame: true, title: 'Nuevo Salon', width: 250, items:[ { //cargamos nuestro comboBox desde la Base de Datos xtype: 'combo', name: 'bloque', fieldLabel: 'Bloque', mode: 'remote', //le aclaramos que será cargado por información traida remotamente store: bloques, //definimos el Store displayField:'BLQ_NOM', hiddenName: 'bloque', width: 130, triggerAction: 'all', //mostrar siempre todas la opciones del combo valueField : 'BLQ_IDE', selectOnFocus: true, emptyText:"Seleccione uno", forceSelection:true, //para que la seleccion no se pierda al perder el foco allowBlank: false }, { xtype: 'textfield', fieldLabel: 'Nombre', name: 'nom_sal', allowBlank: false }, { xtype: 'combo', name: 'est_sal', fieldLabel: 'Estado', mode: 'local', store: estados, displayField:'estado', hiddenName: 'est_sal', width: 130, triggerAction: 'all', //mostrar siempre todas la opciones del combo valueField : 'id', selectOnFocus: true, emptyText:"Seleccione uno", forceSelection:true, //para que la seleccion no se pierda al perder el foco allowBlank: false } ], buttons: [ { text: 'Guardar', handler: function() { Salon_Form.getForm().submit( { success: function(f,a) { Ext.Msg.show({ title: 'Agregado', //<- el título del diálogo msg: 'Salon Agregado Con Exito', //<- El mensaje buttons: Ext.Msg.OK, //<- Boton de Aceptar icon: Ext.Msg.INFO // <- un ícono de Info }); Salon_Form.getForm().reset(); }, failure: function(f,a) { Ext.Msg.alert('Error', a.result.errormsg); } } ); } }, { text: 'Limpiar', handler: function() { Salon_Form.getForm().reset(); } } ] }); //creamos el TabPanel donde iremos agregando los diferentes formularios.. tabs = new Ext.TabPanel({ activeTab: 0, border: true, deferredRender: false }); //agregamos los dos primeros formularios al TabPanel tabs.add(Bloque_Form); tabs.add(Salon_Form); //creamos nuestra ventana y agregamos el TabPanel var win = new Ext.Window({ title: 'Ingresar', width:300, height:250, bodyStyle:'background-color:#fff;padding: 10px', items: tabs //le agregamos el formulario }); win.show(); //mostramos la ventana });el código de la principal quedó de la siguiente manera :
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Ayudas Educativas</title> <link rel="stylesheet" type="text/css" href="lib/resources/css/ext-all.css" /> <script src="lib/adapter/ext/ext-base.js"></script> <script src="lib/ext-all-debug.js"></script> <script src="lib/build/locale/ext-lang-es-min.js"></script> <script src="ingresar.js"></script><!--nuestros archivos deben estar al final de todos los includes de el framework, de otra manera, no funcionará bien --> <script> </script> </head> <body> <!-- Nothing in the body --> </body>Bueno básicamente eso fue lo nuevo que se hizo en esta parte... Espero sus críticas, ideas, opiniones, todas serán bien recibidas..
Bueno ya he ido agregando varios formularios a la ventana.. pero me ha surgido una inquietud cómo hago para no tener que agrandar la ventana cada vez que ingreso un formulario al TabPanel, es decir que haya una forma de que el TabPanel se pueda ir moviendo a derecha o izquierda para poder navegar por todos los Tabs... he buscado información pero nada de lo que hago me funciona..
les dejo una imagen donde muestro más claramente a lo que me refiero:
[url=http://www.servidor-imagenes.com][img]http://www.servidor-imagenes.com/pictures/7643fa435f83b9451131b2b95159ad9f.jpg[/img][/url]
Espero que puedan ayudarme.. <!-- s:( --><!-- s:( -->
Amigo debes utilizar las propiedades:
resizeTabs:true,
enableTabScroll:true,
con eso debe resultar de todas maneras pruebo ahora porque lo acabo de ver en uno de los ejemplos que viene con ExtJs
Muchas gracias por tu consejo.. pero a mi no me funciona con esas propiedades.. creo que debe ser algo más elaborado (espero que no :'( )
si, hay uno en particular que haría lo que necesito... pero no puedo hacerlo funcionar en la ventana.. <!-- m -->http://extjs.com/deploy/dev/examples/tabs/tabs-adv.html<!-- m -->
es algo bien sencillo, te pongo un ejemplo:
this.tabs = new Ext.TabPanel({ region: 'center', margins: '5 5 5 0', activeItem: 0, cls: 'panel-content', enableTabScroll:true, // <--- esto es todo lo que tienes que hacer items: [{ title: 'Home', iconCls:'home-icon', contentEl: 'home' }] });Como puedes ver usando la propiedad [b]enableTabScroll:true[/b] es todo lo necesario! saludos
Muchas gracias Stock.. hice lo que me dijiste y todo funciono.. perfecto: (creo que era el mismo consejo que me habia dado ogonzalezf en unos posts atrás, pero no se porque no me funcionaba... muchas gracias a ogonzalezf tambien)..
tabs = new Ext.TabPanel({ region: 'center', margins: '5 5 5 0', activeItem: 0, activeTab: 0, border: true, deferredRender: false, resizeTabs:true, enableTabScroll:true, resizeTabs:true, minTabWidth: 115, tabWidth:135, width:300, });lo que sigue, comboBoxs anidados..
hace algún tiempo hice un video tutorial al respecto (el primero de todos) esta aquí:
<!-- m -->http://www.crysfel.com/index.php/2008/1 ... on-ext-js/<!-- m -->
espero te sirva, saludos.
Felicidades elcrespo creo que estas trabajando a toda maquina y quiero ayudar aunque con poco, asi que si necesitas hosting te lo brindo y tambien te puedo brindar un subdominio para que coloques tu trabajo, si es que lo necesitas.
Saludos y Felicidades
[quote="stock"]hace algún tiempo hice un video tutorial al respecto (el primero de todos) esta aquí:
<!-- m --><a class="postlink" href="http://www.crysfel.com/index.php/2008/11/26/combos-dependientes-con-ext-js/">http://www.crysfel.com/index.php/2008/1 ... on-ext-js/</a><!-- m -->
espero te sirva, saludos.[/quote]
muchas gracias Stock por el link al video tutorial, está buenísimo.. ahora mismo empiezo a trabajar en ello..
[quote="gustavo"]Felicidades elcrespo creo que estas trabajando a toda maquina y quiero ayudar aunque con poco, asi que si necesitas hosting te lo brindo y tambien te puedo brindar un subdominio para que coloques tu trabajo, si es que lo necesitas.
Saludos y Felicidades[/quote]
Muchas Gracias por tu ofrecimiento gustavo y creo que te lo voy a aceptar, sobre todo para que se valla mostrando los adelantos poco a poco, me parece de lo mejor.. mira voy a enviarte mi correo por interno para que me digas que tengo que hacer.. y de nuevo muchísimas gracias por tu voluntad de ayudar
Bueno se que había dicho que íbamos a mirar algo de comboBox anidados pero antes de eso me encontré con la necesidad de hacer la validación de dos campos de contraseñas (en la parte de agregar un miembro del staff) y aprendí un poco de las validaciones personalizadas, vamos a ver cómo se hizo (teniendo en cuenta algunos ejemplos que hay en extjs.com) y qué entendí , para hacer las validaciones personalizadas utilizamos VTypes, que se encuentra dentro de Ext.form
//Acá irán todas nuestras Validaciones Personalizadas Ext.apply(Ext.form.VTypes, { password : function(val, field) { //validación de dos campos de password if (field.passwordInicial) { var pwd = Ext.getCmp(field.passwordInicial); //se obtiene el password que se digito en el primer cuadro de password return (val == pwd.getValue()); // comparamos los dos campos de password y retornames el resultado booleano } return true; }, passwordText : 'Las Claves NO Coinciden' //texto que saldrá cuando el contenido no coincida });Estos son nuestros dos campo de Password:
{ xtype: 'textfield', fieldLabel: 'Clave', inputType : 'password', name: 'sta_pas', id: 'pass', allowBlank: false }, { xtype: 'textfield', fieldLabel: 'Repite Clave', inputType : 'password', name: 'sta_pass2', vtype: 'password',//le decimos damos el nombre de la validaciones personalizada que creamos al inicio del codigo passwordInicial: 'pass', //el id del campo que tiene donde se ha digitado por primera vez el password!! allowBlank: false }con lo que hemos avanzado ya estamos terminando los formularios de ingreso para todos las tablas, faltan solo dos, incluyendo el de "servicio", que es el más complicado por la cantidad de validaciones (creo que haciendo ése si que aprenderemos a hacer validaciones personalizadas) éste formulario incluira datos dinámicos, combobox anidados y validaciones de todos los colores y sabores, terminando esa parte de los formularios ya entraremos a trabajar los diferentes grids para que nuestro proyecto valla tomando una forma más "respetable". Nuestro Proyecto ya ha ido llenándose de archivos así que trataré de ir subiendolo a un servidor para que lo puedan descargar cuando quieran. por ahora les dejo cómo va nuestro código de ingresar:
// JavaScript Document Ext.onReady(function(){ Ext.QuickTips.init(); Ext.BLANK_IMAGE_URL = 'images/s.gif'; //Hacemos las validaciones Personalizadas Ext.apply(Ext.form.VTypes, { password : function(val, field) { //validación de dos campos de password if (field.passwordInicial) { var pwd = Ext.getCmp(field.passwordInicial); return (val == pwd.getValue()); } return true; }, passwordText : 'Las Claves NO Coinciden' //texto que saldrá cuando el contenido no coincida }); //radio buttons para seleccionar si el video o el equipo hacen parte de la reserva var rsv = new Ext.form.RadioGroup({ fieldLabel: 'Reserva', columns: 2, //muestra los radiobuttons en dos columnas items: [ {boxLabel: 'Si', name: 'reserva', inputValue: 'SI'}, {boxLabel: 'No', name: 'reserva', inputValue: 'NO', checked: true} ] }); var rsv2 = new Ext.form.RadioGroup({ fieldLabel: 'Reserva', columns: 2, //muestra los radiobuttons en dos columnas items: [ {boxLabel: 'Si', name: 'reserva', inputValue: 'SI'}, {boxLabel: 'No', name: 'reserva', inputValue: 'NO', checked: true} ] }); //Store para cargar el comboBox de estados, si esta Activo o Inactivo var estados = new Ext.data.SimpleStore( { fields: ['id', 'estado'], data : [['Act','Activo'],['Inc','Inactivo']] } ); var clsequ = new Ext.data.Store( { reader: new Ext.data.JsonReader( { fields: ['CEQ_IDE','CEQ_NOM'], root: 'equipos' }), proxy: new Ext.data.HttpProxy( { url: 'clasesEqui.php' }), autoLoad: true }); //estore del tipo de Staff var ts = new Ext.data.Store( { reader: new Ext.data.JsonReader( { fields: ['STF_IDE', 'STF_NOM'], root: 'ts' }), proxy: new Ext.data.HttpProxy( { url: 'tipoStaff.php' }), autoLoad: true }); //Store que nos trae los bloques activos var bloques = new Ext.data.Store( { reader: new Ext.data.JsonReader( { fields: ['BLQ_IDE', 'BLQ_NOM'], root: 'bloques' }), proxy: new Ext.data.HttpProxy( { url: 'bloques.php' }), autoLoad: true }); //Store para cargar los diferentes tipos de Equipos de la BD var equipos = new Ext.data.Store( { reader: new Ext.data.JsonReader( { fields: ['TEQ_IDE', 'TEQ_NOM'], root: 'equipos' }), proxy: new Ext.data.HttpProxy( { url: 'equipos.php' }), autoLoad: true }); //Store para cargar los formatos de video de la BD var formatos = new Ext.data.Store( { reader: new Ext.data.JsonReader( { fields: ['FMT_IDE','FMT_NOM'], root: 'formatos' }), proxy: new Ext.data.HttpProxy( { url: 'formatos.php' }), autoLoad: true }); //Formulario para ingresar un Nuevo Bloque var Bloque_Form = new Ext.FormPanel({ url: 'ingBloque.php', //renderTo: document.body, frame: true, title: 'Bloque', width: 250, items:[ { xtype: 'textfield', fieldLabel: 'Nombre', name: 'nom_blq', allowBlank: false }, { xtype: 'combo', name: 'est_blq', fieldLabel: 'Estado', mode: 'local', store: estados, displayField:'estado', hiddenName: 'est_blq', width: 130, triggerAction: 'all', //mostrar siempre todas la opciones del combo valueField : 'id', selectOnFocus: true, emptyText:"Seleccione uno", forceSelection:true, //para que la seleccion no se pierda al perder el foco allowBlank: false } ], buttons: [ { text: 'Guardar', handler: function() { Bloque_Form.getForm().submit( { success: function(f,a) { Ext.Msg.show({ title: 'Agregado', //<- el título del diálogo msg: 'Bloque Agregado Con Exito', //<- El mensaje buttons: Ext.Msg.OK, //<- Boton de Aceptar icon: Ext.Msg.INFO // <- un ícono de Info }); Bloque_Form.getForm().reset(); bloques.load(); }, failure: function(f,a) { Ext.Msg.alert('Error', a.result.errormsg); } } ); } }, { text: 'Limpiar', handler: function() { Bloque_Form.getForm().reset(); } } ] }); //fin del panel // Formulario Para Ingresar Un tipo de formato var Formato_Form = new Ext.FormPanel({ url: 'ingFormato.php', //renderTo: document.body, frame: true, title: 'Formato', width: 250, items:[ { xtype: 'textfield', fieldLabel: 'Nombre', name: 'nom_fmt', allowBlank: false }, { xtype: 'combo', name: 'est_fmt', fieldLabel: 'Estado', mode: 'local', store: estados, displayField:'estado', hiddenName: 'est_fmt', width: 130, triggerAction: 'all', //mostrar siempre todas la opciones del combo valueField : 'id', selectOnFocus: true, emptyText:"Seleccione uno", forceSelection:true, //para que la seleccion no se pierda al perder el foco allowBlank: false } ], buttons: [ { text: 'Guardar', handler: function() { Formato_Form.getForm().submit( { success: function(f,a) { Ext.Msg.show({ title: 'Agregado', //<- el título del diálogo msg: 'Formato Agregado Con Exito', //<- El mensaje buttons: Ext.Msg.OK, //<- Boton de Aceptar icon: Ext.Msg.INFO // <- un ícono de Info }); Formato_Form.getForm().reset(); formatos.load(); }, failure: function(f,a) { Ext.Msg.alert('Error', a.result.errormsg); } } ); } }, { text: 'Limpiar', handler: function() { Formato_Form.getForm().reset(); } } ] });//fin del panel de formato //formato de ingreso de tipo de Staff var Tstaff_Form = new Ext.FormPanel({ url: 'ingTstaff.php', //renderTo: document.body, frame: true, title: 'Tipo Staff', width: 250, items:[ { xtype: 'textfield', fieldLabel: 'Nombre', name: 'nom_tst', allowBlank: false }, { xtype: 'combo', name: 'est_tst', fieldLabel: 'Estado', mode: 'local', store: estados, displayField:'estado', hiddenName: 'est_tst', width: 130, triggerAction: 'all', //mostrar siempre todas la opciones del combo valueField : 'id', selectOnFocus: true, emptyText:"Seleccione uno", forceSelection:true, //para que la seleccion no se pierda al perder el foco allowBlank: false } ], buttons: [ { text: 'Guardar', handler: function() { Tstaff_Form.getForm().submit( { success: function(f,a) { Ext.Msg.show({ title: 'Agregado', //<- el título del diálogo msg: 'Tipo de Staff Agregado Con Exito', //<- El mensaje buttons: Ext.Msg.OK, //<- Boton de Aceptar icon: Ext.Msg.INFO // <- un ícono de Info }); Tstaff_Form.getForm().reset(); tipoStaff.load(); }, failure: function(f,a) { Ext.Msg.alert('Error', a.result.errormsg); } } ); } }, { text: 'Limpiar', handler: function() { Tstaff_Form.getForm().reset(); } } ] });//fin de la forma de ingreso tipo de staff var Salon_Form = new Ext.FormPanel({ url: 'ingSalon.php', //renderTo: document.body, frame: true, title: 'Salon', width: 250, items:[ { xtype: 'combo', name: 'bloque', fieldLabel: 'Bloque', mode: 'remote', store: bloques, displayField:'BLQ_NOM', hiddenName: 'bloque', width: 130, triggerAction: 'all', //mostrar siempre todas la opciones del combo valueField : 'BLQ_IDE', selectOnFocus: true, emptyText:"Seleccione uno", forceSelection:true, //para que la seleccion no se pierda al perder el foco allowBlank: false }, { xtype: 'textfield', fieldLabel: 'Nombre', name: 'nom_sal', allowBlank: false }, { xtype: 'combo', name: 'est_sal', fieldLabel: 'Estado', mode: 'local', store: estados, displayField:'estado', hiddenName: 'est_sal', width: 130, triggerAction: 'all', //mostrar siempre todas la opciones del combo valueField : 'id', selectOnFocus: true, emptyText:"Seleccione uno", forceSelection:true, //para que la seleccion no se pierda al perder el foco allowBlank: false } ], buttons: [ { text: 'Guardar', handler: function() { Salon_Form.getForm().submit( { success: function(f,a) { Ext.Msg.show({ title: 'Agregado', //<- el título del diálogo msg: 'Salon Agregado Con Exito', //<- El mensaje buttons: Ext.Msg.OK, //<- Boton de Aceptar icon: Ext.Msg.INFO // <- un ícono de Info }); Salon_Form.getForm().reset(); }, failure: function(f,a) { Ext.Msg.alert('Error', a.result.errormsg); } } ); } }, { text: 'Limpiar', handler: function() { Salon_Form.getForm().reset(); } } ] });//fin de la forma de ingreso //Formulario para ingresar un Nuevo Tipo Equipo var Tequi_Form = new Ext.FormPanel({ url: 'ingTequi.php', //renderTo: document.body, frame: true, title: 'Tipo Equipo', width: 250, items:[ { xtype: 'textfield', fieldLabel: 'Nombre', name: 'nom_teq', allowBlank: false }, { xtype: 'combo', name: 'est_teq', fieldLabel: 'Estado', mode: 'local', store: estados, displayField:'estado', hiddenName: 'est_teq', width: 130, triggerAction: 'all', //mostrar siempre todas la opciones del combo valueField : 'id', selectOnFocus: true, emptyText:"Seleccione uno", forceSelection:true, //para que la seleccion no se pierda al perder el foco allowBlank: false } ], buttons: [ { text: 'Guardar', handler: function() { Tequi_Form.getForm().submit( { success: function(f,a) { Ext.Msg.show({ title: 'Agregado', //<- el título del diálogo msg: 'Tipo de Equipo Agregado Con Exito', //<- El mensaje buttons: Ext.Msg.OK, //<- Boton de Aceptar icon: Ext.Msg.INFO // <- un ícono de Info }); Tequi_Form.getForm().reset(); equipos.load(); //al terminar de ingresar un tipo de equipo, recargamos el Store que maneja los tipos de equipos en el formulario de Clases de equipos }, failure: function(f,a) { Ext.Msg.alert('Error', a.result.errormsg); } } ); } }, { text: 'Limpiar', handler: function() { Tequi_Form.getForm().reset(); } } ] }); //fin del panel //Formulario para ingresar un Nuevo Tipo Usuario var Tusua_Form = new Ext.FormPanel({ url: 'ingTusua.php', //renderTo: document.body, frame: true, title: 'Tipo Usuario', width: 250, items:[ { xtype: 'textfield', fieldLabel: 'Nombre', name: 'nom_tus', allowBlank: false }, { xtype: 'combo', name: 'est_tus', fieldLabel: 'Estado', mode: 'local', store: estados, displayField:'estado', hiddenName: 'est_tus', width: 130, triggerAction: 'all', //mostrar siempre todas la opciones del combo valueField : 'id', selectOnFocus: true, emptyText:"Seleccione uno", forceSelection:true, //para que la seleccion no se pierda al perder el foco allowBlank: false } ], buttons: [ { text: 'Guardar', handler: function() { Tusua_Form.getForm().submit( { success: function(f,a) { Ext.Msg.show({ title: 'Agregado', //<- el título del diálogo msg: 'Tipo de Usuario Agregado Con Exito', //<- El mensaje buttons: Ext.Msg.OK, //<- Boton de Aceptar icon: Ext.Msg.INFO // <- un ícono de Info }); Tusua_Form.getForm().reset(); }, failure: function(f,a) { Ext.Msg.alert('Error', a.result.errormsg); } } ); } }, { text: 'Limpiar', handler: function() { Tusua_Form.getForm().reset(); } } ] }); //fin del panel //Formulario para ingresar un Nueva Sala Audiovisual var Salau_Form = new Ext.FormPanel({ url: 'ingSalau.php', //renderTo: document.body, frame: true, title: 'Sala', width: 250, items:[ { xtype: 'textfield', fieldLabel: 'Nombre', name: 'nom_slu', allowBlank: false }, { xtype: 'combo', name: 'est_slu', fieldLabel: 'Estado', mode: 'local', store: estados, displayField:'estado', hiddenName: 'est_slu', width: 130, triggerAction: 'all', //mostrar siempre todas la opciones del combo valueField : 'id', selectOnFocus: true, emptyText:"Seleccione uno", forceSelection:true, //para que la seleccion no se pierda al perder el foco allowBlank: false } ], buttons: [ { text: 'Guardar', handler: function() { Salau_Form.getForm().submit( { success: function(f,a) { Ext.Msg.show({ title: 'Agregado', //<- el título del diálogo msg: 'Sala Audiovisual Agregada Con Exito', //<- El mensaje buttons: Ext.Msg.OK, //<- Boton de Aceptar icon: Ext.Msg.INFO // <- un ícono de Info }); Salau_Form.getForm().reset(); }, failure: function(f,a) { Ext.Msg.alert('Error', a.result.errormsg); } } ); } }, { text: 'Limpiar', handler: function() { Salau_Form.getForm().reset(); } } ] }); //fin del panel //Formulario para ingresar un Nueva Clase de Equipo var Clequi_Form = new Ext.FormPanel({ url: 'ingClequi.php', //renderTo: document.body, frame: true, title: 'Clase de Equipo', width: 250, items:[ { xtype: 'combo', name: 'equipo', fieldLabel: 'Tipo de Equipo', mode: 'remote', store: equipos, displayField:'TEQ_NOM', hiddenName: 'equipo', width: 130, triggerAction: 'all', //mostrar siempre todas la opciones del combo valueField : 'TEQ_IDE', selectOnFocus: true, emptyText:"Seleccione uno", forceSelection:true, //para que la seleccion no se pierda al perder el foco allowBlank: false }, { xtype: 'textfield', fieldLabel: 'Codigo Equipo', name: 'idc_ceq', allowBlank: false }, { xtype: 'textfield', fieldLabel: 'Nombre', name: 'nom_ceq', allowBlank: false }, { xtype: 'combo', name: 'est_ceq', fieldLabel: 'Estado', mode: 'local', store: estados, displayField:'estado', hiddenName: 'est_ceq', width: 130, triggerAction: 'all', //mostrar siempre todas la opciones del combo valueField : 'id', selectOnFocus: true, emptyText:"Seleccione uno", forceSelection:true, //para que la seleccion no se pierda al perder el foco allowBlank: false } ], buttons: [ { text: 'Guardar', handler: function() { Clequi_Form.getForm().submit( { success: function(f,a) { Ext.Msg.show({ title: 'Agregado', //<- el título del diálogo msg: 'Clase de Equipo Agregado Con Exito', //<- El mensaje buttons: Ext.Msg.OK, //<- Boton de Aceptar icon: Ext.Msg.INFO // <- un ícono de Info }); Clequi_Form.getForm().reset(); clsequ.load();//al finalizar el ingreso de una Clase de Equipo, recargamos el Store que carga las clases de equipos en el formulario de nuevo video }, failure: function(f,a) { Ext.Msg.alert('Error', a.result.errormsg); } } ); } }, { text: 'Limpiar', handler: function() { Clequi_Form.getForm().reset(); } } ] });//fin de la forma de ingreso var Video_Form = new Ext.FormPanel({ url: 'ingVideo.php', //renderTo: document.body, frame: true, title: 'Video', width: 250, items:[{ xtype:"textfield", fieldLabel:"Codigo Video", name:"vid_ide", allowBlank:false },{ xtype:"combo", fieldLabel:"Formato", name:"formato", hiddenName:"formato", store: formatos, mode: 'remote', displayField:'FMT_NOM', valueField : 'FMT_IDE', width: 130, triggerAction: 'all', //mostrar siempre todas la opciones del combo selectOnFocus: true, emptyText:"Seleccione uno", forceSelection:true, //para que la seleccion no se pierda al perder el foco allowBlank: false },{ xtype:"textfield", fieldLabel:"Titulo", width: 130, name:"vid_tit", allowBlank:false },{ xtype:"combo", fieldLabel:"Area", name:"vid_are", width: 130, hiddenName:"vid_are", allowBlank:false },{ xtype:"textfield", fieldLabel:"Duración (min)", name:"vid_dur", allowBlank:false },{ xtype:"textfield", fieldLabel:"Autor", name:"vid_aut", allowBlank:false },{ xtype:"datefield", fieldLabel:"Date", name:"vid_adq", width: 130, allowBlank:false },{ xtype:"textfield", fieldLabel:"Proveedor", name:"vid_prv", allowBlank:true },{ xtype: 'combo', name: 'vid_est', fieldLabel: 'Estado', mode: 'local', store: estados, displayField:'estado', hiddenName: 'vid_est', width: 130, triggerAction: 'all', //mostrar siempre todas la opciones del combo valueField : 'id', selectOnFocus: true, emptyText:"Seleccione uno", forceSelection:true, //para que la seleccion no se pierda al perder el foco allowBlank: false },rsv], buttons: [ { text: 'Guardar', handler: function() { Video_Form.getForm().submit( { success: function(f,a) { Ext.Msg.show({ title: 'Agregado', //<- el título del diálogo msg: 'Video Agregado Con Exito', //<- El mensaje buttons: Ext.Msg.OK, //<- Boton de Aceptar icon: Ext.Msg.INFO // <- un ícono de Info }); Video_Form.getForm().reset(); }, failure: function(f,a) { Ext.Msg.alert('Error', a.result.errormsg); } } ); } }, { text: 'Limpiar', handler: function() { Video_Form.getForm().reset(); } } ] }); //Formulario para ingresar un Nuevo Miembro del Staff var Staff_Form = new Ext.FormPanel({ url: 'ingStaff.php', //renderTo: document.body, frame: true, title: 'Staff', width: 250, items:[ { xtype: 'combo', name: 'tistaff', fieldLabel: 'Tipo Staff', mode: 'remote', store: ts, displayField:'STF_NOM', hiddenName: 'tistaff', width: 130, triggerAction: 'all', //mostrar siempre todas la opciones del combo valueField : 'STF_IDE', selectOnFocus: true, emptyText:"Seleccione uno", forceSelection:true, //para que la seleccion no se pierda al perder el foco allowBlank: false }, { xtype: 'textfield', fieldLabel: 'Nombre', name: 'sta_nom', allowBlank: false }, { xtype: 'textfield', fieldLabel: 'Apellido', name: 'sta_ape', allowBlank: false }, { xtype: 'textfield', fieldLabel: 'Nick', name: 'sta_nic', allowBlank: false }, { xtype: 'textfield', fieldLabel: 'Clave', inputType : 'password', name: 'sta_pas', id: 'pass', allowBlank: false }, { xtype: 'textfield', fieldLabel: 'Repite Clave', inputType : 'password', name: 'sta_pass2', vtype: 'password',//le decimos damos el nombre de la validaciones personalizada que creamos al inicio del codigo passwordInicial: 'pass', //el id del campo que tiene donde se ha digitado por primera vez el password!! allowBlank: false }, { xtype: 'combo', name: 'est_sta', fieldLabel: 'Estado', mode: 'local', store: estados, displayField:'estado', hiddenName: 'est_sta', width: 130, triggerAction: 'all', //mostrar siempre todas la opciones del combo valueField : 'id', selectOnFocus: true, emptyText:"Seleccione uno", forceSelection:true, //para que la seleccion no se pierda al perder el foco allowBlank: false } ], buttons: [ { text: 'Guardar', handler: function() { Staff_Form.getForm().submit( { success: function(f,a) { Ext.Msg.show({ title: 'Agregado', //<- el título del diálogo msg: 'Miembro del Staff Agregado Con Exito', //<- El mensaje buttons: Ext.Msg.OK, //<- Boton de Aceptar icon: Ext.Msg.INFO // <- un ícono de Info }); Staff_Form.getForm().reset(); }, failure: function(f,a) { Ext.Msg.alert('Error', a.result.errormsg); } } ); } }, { text: 'Limpiar', handler: function() { Staff_Form.getForm().reset(); } } ] }); //fin del panel //Formulario para ingresar un Equipo var Equipo_Form = new Ext.FormPanel({ url: 'ingEquipo.php', //renderTo: document.body, frame: true, title: 'Equipo', width: 250, items:[ { xtype: 'combo', name: 'clase_equ', fieldLabel: 'Clase de Equipo', mode: 'remote', store: clsequ, displayField:'CEQ_NOM', hiddenName: 'clase_equ', width: 130, triggerAction: 'all', //mostrar siempre todas la opciones del combo valueField : 'CEQ_IDE', selectOnFocus: true, emptyText:"Seleccione uno", forceSelection:true, //para que la seleccion no se pierda al perder el foco allowBlank: false }, { xtype: 'textfield', fieldLabel: 'Código del Equipo', name: 'EQU_IDE', allowBlank: false }, { xtype: 'textfield', fieldLabel: 'Serial', name: 'EQU_SER', allowBlank: false }, { xtype: 'textfield', fieldLabel: 'Proveedor', name: 'EQU_PRV' }, { xtype: 'datefield', fieldLabel: 'Adquisición', name: 'EQU_FAD', format: 'Y-m-j', readOnly: true, allowBlank: false }, { xtype: 'textarea', fieldLabel: 'Descripción', width: 130, maxLength :100, name: 'EQU_DSC', }, { xtype: 'combo', name: 'EQU_EST', fieldLabel: 'Estado', mode: 'local', store: estados, displayField:'estado', hiddenName: 'EQU_EST', width: 130, triggerAction: 'all', //mostrar siempre todas la opciones del combo valueField : 'id', selectOnFocus: true, emptyText:"Seleccione uno", forceSelection:true, //para que la seleccion no se pierda al perder el foco allowBlank: false }, rsv2 ], buttons: [ { text: 'Guardar', handler: function() { Equipo_Form.getForm().submit( { success: function(f,a) { Ext.Msg.show({ title: 'Agregado', //<- el título del diálogo msg: 'Miembro del Staff Agregado Con Exito', //<- El mensaje buttons: Ext.Msg.OK, //<- Boton de Aceptar icon: Ext.Msg.INFO // <- un ícono de Info }); Equipo_Form.getForm().reset(); }, failure: function(f,a) { Ext.Msg.alert('Error', a.result.errormsg); } } ); } }, { text: 'Limpiar', handler: function() { Equipo_Form.getForm().reset(); } } ] }); //fin del panel tabs = new Ext.TabPanel({ region: 'center', margins: '5 5 5 0', //renderTo:document.body, activeItem: 0, activeTab: 0, border: true, deferredRender: false, resizeTabs:true, enableTabScroll:true, resizeTabs:true, // turn on tab resizing minTabWidth: 80, width:380, //items: [Bloque_Form,Salon_Form,Formato_Form,Tequi_Form,Tusua_Form,Salau_Form] }); tabs.add(Bloque_Form); tabs.add(Salon_Form); tabs.add(Tstaff_Form); tabs.add(Formato_Form); tabs.add(Tequi_Form); tabs.add(Clequi_Form); tabs.add(Tusua_Form); tabs.add(Salau_Form); tabs.add(Video_Form); tabs.add(Staff_Form); tabs.add(Equipo_Form); // Creamos nuestra primera ventana var win = new Ext.Window({ title: 'Ingresar', width:410, regino: 'center', bodyStyle:'background-color:#fff;padding: 10px', items: [tabs] //le agregamos el formulario }); win.show(); //mostramos la ventana });Por ahora no es más.. en la próxima creo que ya veremos cómo me fue con lo de los comboBox anidados..
bueno muchachos, acá les dejo el archivo con lo que se lleva hasta ahora... No es lo más elaborado (aún) pero creo que vamos por buen camino.. sé que va a salir un muy buen proyecto de todo esto.
Descarga: <!-- m -->http://www.megaupload.com/?d=7VFRNJF0<!-- m -->
no me ha querido funcionar... no sé que estoy haciendo mal:
los comoboBox:
{ xtype: 'combo', name: 'blq', fieldLabel: 'Bloque', mode: 'local', store: bloques, displayField: 'BLQ_NOM', valueField: 'BLQ_IDE', hiddenName : 'blq', triggerAction: 'all', width: 130, selectOnFocus: true, emptyText: 'Seleccione uno', forceSelection: true, //para que la seleccion no se pierda al perder el foco allowBlank: false, listeners: { beforeselect: function(cmb,record,index) { sal.clearValue(); salones.load({params:{bloque:record.get('BLQ_IDE')}}); } } }, { xtype: 'combo', name: 'sal', fieldLabel: 'Salón', mode: 'local', store: salones, displayField: 'SAL_IDE', //valueField: 'SAL_IDE', //hiddenName : 'sal', triggerAction: 'all', width: 130, selectOnFocus: true, emptyText: 'Seleccione uno', forceSelection: true, //para que la seleccion no se pierda al perder el foco allowBlank: false }stores:
var salones = new Ext.data.Store( { reader: new Ext.data.JsonReader( { fields: ['SAL_IDE'], root: 'salones' }), proxy: new Ext.data.HttpProxy({ url: 'salones.php' }) }); //Store que nos trae los bloques activos var bloques = new Ext.data.Store( { reader: new Ext.data.JsonReader( { fields: ['BLQ_IDE', 'BLQ_NOM'], root: 'bloques' }), proxy: new Ext.data.HttpProxy( { url: 'bloques.php' }), autoLoad: true });este es el código php para cargar el comboBox de salones: salones.php
<?php include ("conexion/conexion.php"); mysql_select_db($database_conexion,$conexion); $bloque=$_POST['bloque']; $result=mysql_query("Select SAL_IDE from salon where (BLQ_IDE=$bloque and SAL_EST='Act')"); if($result) { if (mysql_num_rows($result) > 0) { while ($obj = mysql_fetch_object($result)) { $arr[] = $obj; } echo '{success: true, Salones:'.json_encode($arr).'}'; } else echo "{success: false, errormsg: 'No se Encontraron Salones Asignados a ese Bloque'}"; }else{ echo "{success: false, errormsg: 'Error al Consultar la Base de datos'}"; } ?>Gracias por leer!!
ya encontré el error, estaba escribiendo "Salones" en el .php y era "salones" (sin mayúscula), y que no estaba accediendo adecuadamente a el combo y el Store.. ahora el código del listener quedó algo asi:
listeners: { beforeselect: function(cmb,record,index) { sls = Ext.getCmp('sal'); sls.clearValue(); sls.store.load({params:{'bloque':record.get('BLQ_IDE')}}); } }ahora tengo el problema que si selecciono un bloque que tenga salones (hace bien la seleccion) y después selecciono uno que no tenga asignados salones, en el comboBox de salones quedan cargados los últimos asignados al bloque que si tenía salones... no se si me hice entender..
utiliza el método del store del combo "[b]removeAll()[/b]" para quitar todos los registros <!-- s;) --><!-- s;) -->
saludos
<!-- s:o --><!-- s:o --> Muchas gracias Stock.. funcionó perfecto!! <!-- s:D --><!-- s:D --> <!-- s:) --><!-- s:) -->
bueno muchachos.. acabo de subir el proyecto a la web, así que aquí dejo el link para que lo visiten <!-- m -->http://elcrespo.hostei.com/<!-- m --> , no está bonito (aún) pero vamos avanzando poco a poco.
ahora que está online quiero que que vean un problema que me están dando los comboBox y es que el contenido se está mostrando en un espacio mucho más pequeño que el width del comboBox..
Alguna idea para solucionar este problema??
desde ya Gracias por sus respuestas!!
elcrespo estuve probando lo que subiste al hosting y da algunos errores cuando vas a ingresar un bloque por ejemplo que fue lo que intenté insertar, mirando mi consola firebug me parece que es que el hosting está agregando a todas tus páginas un JS en tu respuesta json y por eso ocurren los problemas revisalo para que veas.
saludos
como te comenta ogonzalezf, el server esta añadiendo esto a las respuestas:
<!-- www.000webhost.com Analytics Code --> <script type="text/javascript" src="http://analytics.hosting24.com/count.php"></script> <noscript><a href="http://www.hosting24.com/"><img src="http://analytics.hosting24.com/count.php" alt ="web hosting" /></a></noscript> <!-- End Of Analytics Code -->saludos
si es cierto.. lo había probado recién subí los archivos y funcionaba todo muy bien, ahora no carga ningun comboBox, ni ingresa nada a la base de datos.. ese código me dañó todo.. el problema del hosting gratuito :'( <!-- s:( --><!-- s:( --> ... por ahora solo queda seguir buscando a ver donde puedo colgar el proyecto..
muchas gracias por mirar y avisar del problema!!
un abrazo
Hola elcrespo, siento mucho el tiempo q me perdi tuve que viajar dame hasta la noche y tendras 100mb de hosting y un subdominio, te lo prometo
Bueno muchachos.. gracias a gustavo ahora ya hay espacio para colgar el proyecto, lo acabo de colgar creo que ahora si esta sirviendo. En estos momentos estoy experimentando con un EditorGridPanel, más tarde subiré lo que llevo en este tema y expondré las dudas que llevo..
<!-- m -->http://extjs.consultora-devian.net/<!-- m -->
MUCHISIMAS GRACIAS GUSTAVO!!! <!-- s:D --><!-- s:D --> <!-- s:D --><!-- s:D -->
amigo te recomiendo que revises la codificación utilizada pues no estan saliendo los acentos y demás caracteres, otra cosa no veo el formulario de insertar area y cuando vas a insertar un video te pide area y no veo formulario alguno para insertar y lo otro es que cuando despliegas los combo la lista queda pequeña no se despliega con el tamaño del combo sino con el tamaño de la palabra que viene dentro de ella.
Muchas gracias por tus observaciones ogonzalezf.. lo de los comboBox es algo que no he sabido como solucionarlo, el comboBox de area de los videos debe ser llenado desde otra base de datos (aun no subo la base de datos ni codifico el comboBox) y la codificación pues no se que pasó voy a ver como se soluciona esa parte..
De nuevo muchas gracias por tus observaciones
bueno muchachos mientras que miro como solucionar los problemas que encontró ogozalezf quiero mostrarles la otra parte que estoy probando, los editorGrid.
Bueno, para esta tarea elegí la tabla bloque (pequeña).. lo primero que se debe hice fue crear los campos que servirán para editar los valores de los bloques, aunque cabe aclarar que no es estrictamente necesario hacerlo pues se puede hacer más adelante:
var bloque_edit = new Ext.form.TextField(); bloque_edit.allowBlank=false; //variable para editar el estado del bloque var estado_edit=new Ext.form.ComboBox({ mode: 'local', store: estados, displayField:'estado', hiddenName: 'EQU_EST', triggerAction: 'all', //mostrar siempre todas la opciones del combo valueField : 'id', selectOnFocus: true, emptyText:"Seleccione uno", forceSelection:true, //para que la seleccion no se pierda al perder el foco allowBlank: false});después de esto, declaré el ColumnModel de nuestro grid:
var BloqueColumnModel = new Ext.grid.ColumnModel([ new Ext.grid.RowNumberer(), //numerar {id:'BLQ_IDE',header: "ID", width: 80, sortable: true, dataIndex: 'BLQ_IDE'}, {header: "Bloque", width: 80, sortable: true, dataIndex: 'BLQ_NOM', editor: bloque_edit/*una de las variables que creamos al comienzo, sino quieres declararlas puedes dar todos los detalles del editor en esta parte*/}, {header: "Estado", width: 80, sortable: true, dataIndex: 'BLQ_EST', editor: estado_edit } ]); //Para ir cambiando un poco lo forma poco Ortodoxa de ingresar los datos vamos a crear una ventana que solo contendra el formulario de ingresar Bloque var wingBloque=new Ext.Window({ title: 'Ingresar Bloque', id: 'wingBloque', width: 300, closeAction : 'hide' });ahora vamos a crear nuestro primer editorGridPanel:
var grid = new Ext.grid.EditorGridPanel( { id: 'grid', singleSelect: true, //permita seleccionar un solo registro // clickstoEdit: 2,//clicks necesarios para permitir editar un campo title: 'Bloques', height:300, width:300, stripeRows: true, store: allbloques, cm: BloqueColumnModel, //referenciamos el colomnModel que creamos unas lineas atras tbar: [//creamos una barra para agregarse al editorGrid { text: 'Agregar Bloque', //creamos el botón para agregar un bloque handler: function(){ wingBloque.show();//le decimos que nos muestre la ventana con el formulario para ingresar el bloque } } ], /*en esta parte declaramos los listeners del grid.. en este caso le diremos que debe hacer después de editar un campo, por lo que consulte se puede tomar la decisión de ingresar a la base de datos cada vez que se hace un cambio, cuando el usuario desee guardar los cambios que ha hecho y/o hacer un guardado automático cada cantidad de tiempo yo decidí hacerlo (por ahora) eligiendo la primera opción, guardar los cambios cada vez que se edita un campo*/ listeners: { afteredit: function(e){ //que debe hacer después de editar un campo var conn = new Ext.data.Connection(); //nos conectamos por medio de Ajax conn.request({ url: 'bloques-update.php', params: { //enviamos los parámetros necesarios para la edicion del registro id: e.record.data.BLQ_IDE, //el id del registro editado field: e.field, //el campo del registro que fue editado value: e.value //el nuevo valor del campo }, success: function(resp,opt) { //que hacer si se pudo editar correctamente e.grid.store.commitChanges(); //acá le decimos al store que acepte y guarde los cambios (deje el valor editado y quite la marquita roja que aparece en los datos que han sido modificados pero que no han sido guardados) }, failure: function(resp,opt) { //que rechace los cambios hechos e.grid.store.reject(); } }); } } }); //agregamos el formulario de ingresar bloque a la ventana wingBloque.add(Bloque_Form);un detalle a tener en cuenta, en el handler del boton guardar de Bloque_Form (formulario de ingreso de un bloque), cuando tengamos éxito debemos recargar el store que maneja los datos de nuestro Grid: entonces esa parte quedaría algo asi:
handler: function() { Bloque_Form.getForm().submit( { success: function(f,a) { Ext.Msg.show({ title: 'Agregado', //<- el titulo del dialogo msg: 'Bloque Agregado Con Exito', //<- El mensaje buttons: Ext.Msg.OK, //<- Boton de Aceptar icon: Ext.Msg.INFO // <- un icono de Info }); Bloque_Form.getForm().reset(); bloques.load(); //acá recargamos el store que se maneja para ingresar salones allbloques.load();//<-- acá le decimos que recargue el store de nuestro grid }, failure: function(f,a) { Ext.Msg.alert('Error', a.result.errormsg); } } ); }bueno por ahora eso es lo nuevo que se ha hecho.. voy a subirlo para que se vea cómo está quedando (éste primero se mostrará sobre la ventana principal mientras cuadro bien lo de los menus) Espero sus comentarios, consejos y/o críticas.
Bueno muchachos ya termine mi primer grid.. ya inserta, pagina, edita y le implemente un plugin de filtrado.. si quieren ya pueden ver como va todo.. más adelante cuando tenga un poco más de tiempo dejo explicado un poco todo lo nuevo que he hecho... vamos avanzando.. poco a poco pero firme!!
Se me han presentado algunas dudas en medio de todo esto.. pero mañana las colocaré mas tranquilamente..
Bueno muchachos, después de una pequeña pausa volví con todo a esto del proyecto.. ya voy avanzando con los grids.. ya hice el de video, pero haciendo ese se me está presentando un problema y es que al querer editar la un campo de fecha (adquisicion) me está leyendo la fecha en formato: [b]"Sat Jun 27 2009 00:00:00 GMT+0200 (Hora de verano romance)"[/b] y no me lo ingresa bien a la base de datos... además el calendario se inicia en el año 1900 <!-- s:shock: --><!-- s:shock: --> <!-- s:| --><!-- s:| -->
asi declaré mi datefield para modificar:
var vid_adq_edit = new Ext.form.DateField({ allowBlank:false, format: 'Y/m/d' });y así lo tengo en el campo del columnmodel:
{header: "Adquisicion",sortable:true, dataIndex:'VID_ADQ', editor: vid_adq_edit}me podrían decir que estoy haciendo mal?? si quieren pueden ver en la pagina del proyecto el avance y el problema que se está presentado: <!-- m -->http://extjs.consultora-devian.net/<!-- m --> salu2
te falta un renderer en la definicion de esa columna y algo como esto en el store
//definicion de fields en el store {name: 'availDate', mapping: 'availability', type: 'date', dateFormat: 'm/d/Y'},y un renderer para que lo muestre con el formato adecuado
//codigo de la definicion del column { header: "Available", dataIndex: 'availDate', width: 95, renderer: formatDate, } //renderer function formatDate(value){ return value ? value.dateFormat('M d, Y') : ''; }
me parece que ya estas en condiciones de publicar el código para esta nueva versión que haz hecho me parece que esta correcto aunque creo que la interfaces deben mejorar un poco más quizas es hora de pensar en lo que te sugerí al empezar este post
[quote="manduks"]te falta un renderer en la definicion de esa columna y algo como esto en el store
<div class="codewrapper"><div class="codetitle"><b>Code:</b></div><div class="codecontent">
//definicion de fields en el store
{name: 'availDate', mapping: 'availability', type: 'date', dateFormat: 'm/d/Y'},
</div></div>
y un renderer para que lo muestre con el formato adecuado
<div class="codewrapper"><div class="codetitle"><b>Code:</b></div><div class="codecontent">
//codigo de la definicion del column
{
header: "Available",
dataIndex: 'availDate',
width: 95,
renderer: formatDate,
}
//renderer
function formatDate(value){
return value ? value.dateFormat('M d, Y') : '';
}
</div></div>[/quote]
Gracias por el consejo. pero trate de hacer lo que me dijiste pero no me funcionó bien.. mira este es mi store:
//Store de TODOS los videos var allVideos = new Ext.data.Store({ reader: new Ext.data.JsonReader({ fields: ['VID_IDE','FMT_IDE','VID_TIT','VID_ARE','VID_DUR','VID_AUT','VID_ADQ','VID_PRV','VID_RES','VID_EST','VID_RSV','FMT_NOM'], root: 'root' }), proxy: new Ext.data.HttpProxy({ url: 'consultas.php?cons=allVideos' }), autoLoad: true });Y este es una parte del código que tengo del Grid:
//campos para editar los datos en el grid var vid_adq_edit = new Ext.form.DateField({ allowBlank:false, format: 'Y/m/d' }); var VideoColumnModel = new Ext.grid.ColumnModel([ new Ext.grid.RowNumberer(), //numerar //new Ext.grid.CheckboxSelectionModel(), {id: 'VID_IDE', header: "ID", width: 80, sortable: true, dataIndex: 'VID_IDE'}, {header: "Titulo", width: 80, sortable: true, dataIndex: 'VID_TIT',editor: vid_tit_edit}, {header: "Formato", width: 80, sortable: true, dataIndex: 'FMT_NOM',editor: fmt_ide_edit}, {header: "Area", sortable: true, dataIndex: 'VID_ARE',editor: vid_are_edit}, {header: "Duracion", width:50, sortable: true, dataIndex: 'VID_DUR',editor: vid_dur_edit}, {header: "Autor", sortable:true, dataIndex: 'VID_AUT',editor: vid_aut_edit}, {header: "Adquisicion",sortable:true, dataIndex:'VID_ADQ', editor: vid_adq_edit}, {header: "Proveedor", sortable:true, dataIndex:'VID_PRV',editor: vid_prv_edit}, {header: "Resenia", sortable:true,dataIndex:'VID_RES',editor: vid_res_edit}, {header: "Reserva", sortable:true,width:50, dataIndex:'VID_RSV'}, {header: "Estado", sortable:true,width:50, dataIndex: 'VID_EST',editor:vid_est_edit} ]); //creamos una ventana que solo contendra el formulario de ingresar Video var wingVideo=new Ext.Window({ title: 'Ingresar Video', id: 'wingVideo', width: 300, closeAction : 'hide' }); wingVideo.add(Video_Form); var filtrosVideo = new Ext.ux.grid.GridFilters({filters:[ {type: 'string', dataIndex: 'VID_IDE'}, {type: 'string', dataIndex: 'VID_ARE'}, {type: 'string', dataIndex: 'VID_DUR'}, {type: 'string', dataIndex: 'VID_AUT'}, {type: 'date', dataIndex: 'VID_ADQ'}, {type: 'string', dataIndex: 'VID_PRV'}, {type: 'string', dataIndex: 'VID_EST'}, {type: 'string', dataIndex: 'VID_RSV'} ]}); var gridVideo = new Ext.grid.EditorGridPanel( { //renderTo: document.body, id: 'gridVideo', singleSelect: true, //permita seleccionar un solo registro // clickstoEdit: 1, title: 'Video', height:300, width:800, stripeRows: true, store: allVideos, cm: VideoColumnModel, tbar: [ { xtype: 'tbbutton', iconCls: 'addRegistro', text: 'Video', handler: function(){ wingVideo.show(); } }, ], plugins: filtrosVideo, bbar: new Ext.PagingToolbar({ pageSize: 10, store: alltipoStaff }), listeners: { afteredit: function(e){ var conn = new Ext.data.Connection(); conn.request({ url: 'ingBD.php?upd=video', params: { id: e.record.data.VID_IDE, field: e.field, value: e.value }, success: function(resp,opt) { e.grid.store.commitChanges(); allVideos.load(); }, failure: function(resp,opt) { e.grid.store.reject(); } }); } } });hice los cambios que me sugeriste pero no me funcionaron (algo tiene que estarseme pasando <!-- s:( --><!-- s:( --> ).... [quote="ogonzalezf"]me parece que ya estas en condiciones de publicar el código para esta nueva versión que haz hecho me parece que esta correcto aunque creo que la interfaces deben mejorar un poco más quizas es hora de pensar en lo que te sugerí al empezar este post[/quote] Hoy o mañana publicaré todo el código... y en cuanto a tu idea creo que también es hora de irla implementando.. pero ahí voy a necesitar de tu ayuda y asesoría (si no es mucho pedir <!-- s;) --><!-- s;) --> ) muchas gracias a los dos por sus consejos y ayuda. salu2
bueno muchachos ya voy terminado la parte de ingresar y modificar, aunque aun me falta arreglar el tamaño de los panel y las ventanas...aún me está dando error el campo de modificar fecha (ya veremos cómo se soluciona) por ahora iniciaré la parte más importante de esta parte de ingresar y es la de ingresar un servicio, yo pueden ver los últimos avances en la pagina del proyecto, acá les dejo el la dirección para que descarguen todo el código:
<!-- m -->http://www.megaupload.com/?d=3CEI5VTM<!-- m --> (incluye las dos bases de datos con las que se está trabajando pero solo con las tablas que se están usando hasta éste momento)
más adelante explicaré con detalle todo lo que se ha hecho (apenas tenga algo de tiempo).
nota: ogonzalezf estoy tratando de implementar tu idea.. vamos a ver que tal me resulta.
Bueno muchachos hoy voy a explicar un poco lo que he hecho..
bueno.. lo primero que hice fue unir todos los archivos de consulta php en un solo archivo y trabajar con variables enviadas mediante método Get y de acuerdo al valor de la variable que envío se realiza la consulta correspondiente.
Lo mismo que hice con las consultas lo hice con los ingresos y updates, es decir, dejes las cosultas en un solo archivo y los insert y updates en otro, también hice otro archivo encargado de la conexión a la otra base de datos con la que he empezado a trabajar.
ahora voy a tratar de explicar el procedimiento que seguí para realizar un Grid editable implementando un plugin de filtrado.
primero cuadremos lo que necesitamos para hacer funcionar correctamente el plugin de filtrado:
1) Podemos descarga el plugin de [url=http://extjs.com/forum/showthread.php?t=14503]acá[/url]
2) Necesitamos el código php que lo maneja:
$where = " 0 = 0 "; if (is_array($filter)) { for ($i=0;$i<count($filter);$i++){ switch($filter[$i]['data']['type']){ case 'string' : $qs .= " AND ".$filter[$i]['field']." LIKE '%".$filter[$i]['data']['value']."%'"; Break; case 'list' : if (strstr($filter[$i]['data']['value'],',')){ $fi = explode(',',$filter[$i]['data']['value']); for ($q=0;$q<count($fi);$q++){ $fi[$q] = "'".$fi[$q]."'"; } $filter[$i]['data']['value'] = implode(',',$fi); $qs .= " AND ".$filter[$i]['field']." IN (".$filter[$i]['data']['value'].")"; }else{ $qs .= " AND ".$filter[$i]['field']." = '".$filter[$i]['data']['value']."'"; } Break; case 'boolean' : $qs .= " AND ".$filter[$i]['field']." = ".($filter[$i]['data']['value']); Break; case 'numeric' : switch ($filter[$i]['data']['comparison']) { case 'ne' : $qs .= " AND ".$filter[$i]['field']." != ".$filter[$i]['data']['value']; Break; case 'eq' : $qs .= " AND ".$filter[$i]['field']." = ".$filter[$i]['data']['value']; Break; case 'lt' : $qs .= " AND ".$filter[$i]['field']." < ".$filter[$i]['data']['value']; Break; case 'gt' : $qs .= " AND ".$filter[$i]['field']." > ".$filter[$i]['data']['value']; Break; } Break; case 'date' : switch ($filter[$i]['data']['comparison']) { case 'ne' : $qs .= " AND ".$filter[$i]['field']." != '".date('Y-m-d',strtotime($filter[$i]['data']['value']))."'"; Break; case 'eq' : $qs .= " AND ".$filter[$i]['field']." = '".date('Y-m-d',strtotime($filter[$i]['data']['value']))."'"; Break; case 'lt' : $qs .= " AND ".$filter[$i]['field']." < '".date('Y-m-d',strtotime($filter[$i]['data']['value']))."'"; Break; case 'gt' : $qs .= " AND ".$filter[$i]['field']." > '".date('Y-m-d',strtotime($filter[$i]['data']['value']))."'"; Break; } Break; } } $where .= $qs; } $query = "SELECT * FROM demo WHERE ".$where;Después de eso dentro de nuestro sitio creamos una carpeta donde vamos a colocar los archivos de todos los plugins que vamos a utilizar.. en mi caso la deje con el nombre de "ux" copiamos los archivos correspondientes al plugin dentro de la carpeta y luego los invocamos en nuestro index, quedando algo asi:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Ayudas Educativas</title> <link rel="stylesheet" type="text/css" href="lib/resources/css/ext-all.css" /> <link rel="stylesheet" type="text/css" href="images.css" /> <link rel="stylesheet" type="text/css" href="css/icons.css"> <link rel="stylesheet" type="text/css" href="css/Ext.ux.grid.RowActions.css"> <link rel="stylesheet" type="text/css" href="css/empty.css" id="theme"> <link rel="stylesheet" type="text/css" href="css/webpage.css"> <link rel="stylesheet" type="text/css" href="css/gridsearch.css"> <script src="lib/adapter/ext/ext-base.js"></script> <script src="lib/ext-all-debug.js"></script> <script src="lib/build/locale/ext-lang-es-min.js"></script> <script src="ext-fix.js"></script> <!-- estos son los archivos necesarios para el filtro--> <script type="text/javascript" src="ux/menu/EditableItem.js"></script> <script type="text/javascript" src="ux/menu/RangeMenu.js"></script> <script type="text/javascript" src="ux/grid/GridFilters.js"></script> <script type="text/javascript" src="ux/grid/filter/Filter.js"></script> <script type="text/javascript" src="ux/grid/filter/StringFilter.js"></script> <script type="text/javascript" src="ux/grid/filter/DateFilter.js"></script> <script type="text/javascript" src="ux/grid/filter/ListFilter.js"></script> <script type="text/javascript" src="ux/grid/filter/NumericFilter.js"></script> <script type="text/javascript" src="ux/grid/filter/BooleanFilter.js"></script> <script src="ingresar.js"></script> <script> </script> </head> <body> <!-- Nothing in the body --> </body>[b]Nota: si estas trabajando con la version 3.X debes agregar un archivo para arreglar un problema que se da con estas versiones, así, antes de llamar los archivos de los filtros debes invocar un archivo al que yo he llamado "ext-fix.js" (puedes colocarle el nombre que quieras) el código que debe tener es el siguiente: [/b]
Ext.grid.GridView.prototype.handleHdMenuClick = function(item){ var index = this.hdCtxIndex; var cm = this.cm, ds = this.ds; switch (item.getItemId()) { case "asc": ds.sort(cm.getDataIndex(index), "ASC"); break; case "desc": ds.sort(cm.getDataIndex(index), "DESC"); break; default: index = cm.getIndexById(item.getItemId().substr(4)); if (index != -1) { if (item.checked && cm.getColumnsBy(this.isHideableColumn, this).length <= 1) { this.onDenyColumnHide(); return false; } cm.setHidden(index, item.checked); } } return true; }Después de tener todo esto listo, ya podemos empezar con el desarrollo de nuestro primer Grid editable con filtros implementados. acá es donde deben implementar la parte de empaquetado del código que ya varias veces se ha explicado en el foro algo como esto:
com.quizzpot.tutorial.gridEditable = { init: function(){ //aqui va el codigo } } Ext.onReady(com.quizzpot.tutorial.gridEditable.init,com.quizzpot.tutorial.gridEditable);después de eso empezamos con el código (vamos a hacer un grid de solo tres columnas): empezamos con los stores:
//Store para cargar el comboBox de estados, si esta Activo o Inactivo var estados = new Ext.data.SimpleStore( { fields: ['id', 'estado'], data : [['Act','Activo'],['Inc','Inactivo']] } ); //store que me trae TODOS los bloques var allbloques = new Ext.data.Store( { reader: new Ext.data.JsonReader( { fields: ['BLQ_IDE', 'BLQ_NOM','BLQ_EST'], root: 'root', totalProperty: 'results' }), proxy: new Ext.data.HttpProxy( { url: 'consultas.php?cons=allbloques' }), autoLoad: true });Hacemos nuestro formulario de ingreso de un bloque:
//Formulario para ingresar un Nuevo Bloque var Bloque_Form = new Ext.FormPanel({ url: 'ingBD.php?ing=bloque', //<-- a donde será enviado el formulario //renderTo: document.body, frame: true, title: 'Bloque', width: 250, items:[ { xtype: 'textfield', fieldLabel: 'Nombre', name: 'nom_blq', allowBlank: false }, { //combo para seleccionar el estado del bloque (activo-inactivo) xtype: 'combo', name: 'est_blq', fieldLabel: 'Estado', mode: 'local', store: estados, displayField:'estado', hiddenName: 'est_blq', width: 130, triggerAction: 'all', //mostrar siempre todas la opciones del combo valueField : 'id', selectOnFocus: true, emptyText:"Seleccione uno", forceSelection:true, //para que la seleccion no se pierda al perder el foco allowBlank: false } ], buttons: [ //agregamos los botones del formulario { text: 'Guardar', //<--Boton de enviar el formularioi handler: function() //declaramos una función anónima para el manejo del boton { Bloque_Form.getForm().submit( //<-- cuando den click sobre el boton, enviamos el formulario { success: function(f,a) //<-- en caso que se haya podido ingresar a la base de datos { Ext.Msg.show({ title: 'Agregado', //<- el titulo del dialogo msg: 'Bloque Agregado Con Exito', //<- El mensaje buttons: Ext.Msg.OK, //<- Boton de Aceptar icon: Ext.Msg.INFO // <- un icono de Info }); Bloque_Form.getForm().reset(); //<-- dejamos en blanco el formulario de nuevo //bloques.load(); allbloques.load();//<-- recargamos el store que manejará nuestro grid editable para que veamos los cambios automáticamente }, failure: function(f,a)//<-- en caso de fallo al ingresar la información en la base de datos, informamos del error ocurrido { Ext.Msg.alert('Error', a.result.errormsg); } } ); } }, { text: 'Limpiar',//<-- boton para limpiar el formulario handler: function() { Bloque_Form.getForm().reset(); } } ] }); //fin del panel //creamos una ventana que solo contendra el formulario de ingresar Bloque var wingBloque=new Ext.Window({ title: 'Ingresar Bloque', id: 'wingBloque', width: 300, closeAction : 'hide' }); wingBloque.add(Bloque_Form);//<-- agregamos el formulario a la ventanaAhora nos encargamos de las variables que nos ayudaran a editar cada una de las columnas de nuestro grid:
//variable para editar el nombre del bloque en var bloque_edit = new Ext.form.TextField(); bloque_edit.allowBlank=false; //variable para editar el estado del bloque var estado_edit=new Ext.form.ComboBox({ mode: 'local', store: estados, displayField:'estado', hiddenName: 'EQU_EST', triggerAction: 'all', //mostrar siempre todas la opciones del combo valueField : 'id', selectOnFocus: true, emptyText:"Seleccione uno", forceSelection:true, //para que la seleccion no se pierda al perder el foco allowBlank: false});luego creamos los filtros que le aplicaremos a nuestro Grid:
var filtrosBloque = new Ext.ux.grid.GridFilters({filters:[ //soporta filtros tipo entero, string, boolean, date {type: 'string', dataIndex: 'BLQ_EST'}, {type: 'string', dataIndex: 'BLQ_NOM'} ]});Hacemos el ColumnModel y le asignamos a cada campo su editor correspondiente :
var BloqueColumnModel = new Ext.grid.ColumnModel([ new Ext.grid.RowNumberer(), //numerar //new Ext.grid.CheckboxSelectionModel(), {id:'BLQ_IDE',header: "ID", width: 80, sortable: true, dataIndex: 'BLQ_IDE'}, //<-- campo que no se permite editar {header: "Bloque", width: 80, sortable: true, dataIndex: 'BLQ_NOM', editor: bloque_edit}, {header: "Estado", width: 80, sortable: true, dataIndex: 'BLQ_EST', editor: estado_edit } ]);Después de esto creamos nuestro Grid editable, hay varias formas de hacer la edición de los campos, puedes elegir hacerlo en lote, cada cierta cantidad de tiempo, o edición por edición, esta última es la que haremos (por ahora). así que cada vez que hagamos una modificación en un campo se guardará automáticamente en la base de datos:
var gridBloque = new Ext.grid.EditorGridPanel( { //renderTo: document.body, id: 'gridBloque', singleSelect: true, //permita seleccionar un solo registro // clickstoEdit: 1, title: 'Bloques', height:300, width:500, stripeRows: true, store: allbloques,//<-- el store que declaramos al comienzo cm: BloqueColumnModel, //<-- asignamos el columnmodel tbar: [ //creamos un tbar que tendrá el boton que nos permitirá agregar un bloque { xtype: 'tbbutton', iconCls: 'addRegistro', text: 'Bloque', handler: function(){ wingBloque.show();//<-- le decimos que al dar click en el boton nos muestre la ventana con el formulario de bloque } }, ], plugins: filtrosBloque, //<-- AGREGAMOS LOS FILTROS QUE DECLARAMOS UNAS LINEA ANTES bbar: new Ext.PagingToolbar({//<-- Agregamos la barra para la paginar nuestra grilla pageSize: 10, //<-- le decimos muestre diez por cada página store: allbloques }), listeners: { afteredit: function(e){ //qué debe hacer despues de que un campo es editado var conn = new Ext.data.Connection(); conn.request({ //hacemos la conexion url: 'ingBD.php?upd=bloque', params: { //que parametros enviamos id: e.record.data.BLQ_IDE, //el ID de la fila que se edito field: e.field, //la columna que fue editada value: e.value //y el nuevo valor que le colocamos }, success: function(resp,opt) { //si se edito correctamente e.grid.store.commitChanges(); //confirmamos cambio en el Store // bloques.load(); }, failure: function(resp,opt) { //si hubo errores al momento de editar rechazamos los cambios e.grid.store.reject(); } }); } } });Creamos la ventana que contendrá el grid y agregamos el grid a la ventana:
var winBloqueGrid = new Ext.Window({ id: 'winBloqueGrid', closable:true, width: 300, closeAction : 'hide', bodyStyle:'background-color:#fff' }); winBloqueGrid.add(gridBloque);Ahora creamos la ventana principal :
var principal = new Ext.Window({ title: 'Ayudas Educativas', id: 'principal', closable:false, //<-- no dejamos que se pueda cerrar width: 300, height: 410, regino: 'center', draggable:false, //<-- hacemos que no la puedan mover ( arrastrar) bodyStyle:'background-color:#fff' });Creamos la toolbar de la ventana principal:
var toolbar = new Ext.Toolbar({ items: [ { xtype: 'tbbutton', text: 'INGRESAR', iconCls: 'ingresar', menu: [{text:'Bloque', iconCls: 'ingresar', //iconAlign: 'top', handler: function() //al dar click nos muestre el grid de bloque { Ext.getCmp('winBloqueGrid').show(); }} }); //agregamos la toolbar a la ventana principal principal.add(toolbar); //mostramos la ventana principal: principal.show();[b]Hasta acá la parte del archivo .js ahora miraremos la parte del lado del servidor, los archivos .php[/b] el archivo de consultas.php quedaría de la siguiente manera:
<?php Include('conexion/conexion.php'); //<-- incluimos el archivo con los detalles de la conexion //include('conexion/conexionSEAD.php'); //hacemos la seleccion de la base de datos mysql_select_db($database_conexion,$conexion); //estas son las variables que manejaran la parte de la paginacion de los datos en nuestro Grid $start = ($_REQUEST['start'] != '') ? $_REQUEST['start'] : 0; $limit = ($_REQUEST['limit'] != '') ? $_REQUEST['limit'] : 10; //inicializamos la variable where en una comparacion cierta $where = " 0 = 0 "; //miramos si el llamado fue echo por un filtro del Grid if(isset($_REQUEST["filter"])){ $filter = $_REQUEST["filter"]; if (is_array($filter)) { for ($i=0;$i<count($filter);$i++){ switch($filter[$i]['data']['type']){ case 'string' : $qs .= " AND ".$filter[$i]['field']." LIKE '%".$filter[$i]['data']['value']."%'"; Break; case 'list' : if (strstr($filter[$i]['data']['value'],',')){ $fi = explode(',',$filter[$i]['data']['value']); for ($q=0;$q<count($fi);$q++){ $fi[$q] = "'".$fi[$q]."'"; } $filter[$i]['data']['value'] = implode(',',$fi); $qs .= " AND ".$filter[$i]['field']." IN (".$filter[$i]['data']['value'].")"; }else{ $qs .= " AND ".$filter[$i]['field']." = '".$filter[$i]['data']['value']."'"; } Break; case 'boolean' : $qs .= " AND ".$filter[$i]['field']." = ".($filter[$i]['data']['value']); Break; case 'numeric' : switch ($filter[$i]['data']['comparison']) { case 'ne' : $qs .= " AND ".$filter[$i]['field']." != ".$filter[$i]['data']['value']; Break; case 'eq' : $qs .= " AND ".$filter[$i]['field']." = ".$filter[$i]['data']['value']; Break; case 'lt' : $qs .= " AND ".$filter[$i]['field']." < ".$filter[$i]['data']['value']; Break; case 'gt' : $qs .= " AND ".$filter[$i]['field']." > ".$filter[$i]['data']['value']; Break; } Break; case 'date' : switch ($filter[$i]['data']['comparison']) { case 'ne' : $qs .= " AND ".$filter[$i]['field']." != '".date('Y-m-d',strtotime($filter[$i]['data']['value']))."'"; Break; case 'eq' : $qs .= " AND ".$filter[$i]['field']." = '".date('Y-m-d',strtotime($filter[$i]['data']['value']))."'"; Break; case 'lt' : $qs .= " AND ".$filter[$i]['field']." < '".date('Y-m-d',strtotime($filter[$i]['data']['value']))."'"; Break; case 'gt' : $qs .= " AND ".$filter[$i]['field']." > '".date('Y-m-d',strtotime($filter[$i]['data']['value']))."'"; Break; } Break; } } $where .= $qs; } }//fin if(isset($_REQUEST["filter"])) if(isset($_REQUEST["cons"])) //miramos si la variable que recibimos una variable de consulta { $cons=$_REQUEST["cons"]; switch($cons){ //hacemos un switch que depende del valor que traiga la variable $cons case 'allbloques': $result=mysql_query("SELECT * FROM bloque where ".$where." LIMIT ".$start.",".$limit); $count_sql = "SELECT * FROM bloque"; //para llevar el total de bloques que hay en la BD $rs = mysql_query($count_sql); break; } } $arr = array(); If ($result){ $results = mysql_num_rows($rs); while($obj = mysql_fetch_object($result)) { $arr[] = $obj; } Echo '{success:true,results:'.$results.',root:'.json_encode($arr).'}'; }else{ $x=mysql_error(); echo "{success: false, errormsg: \"$x\"}"; }el archivo inBD.php (se encarga de ingresar y actualizar en la base de datos):
include ("conexion/conexion.php"); mysql_select_db($database_conexion,$conexion); if(isset($_REQUEST["ing"])) { $ing=$_REQUEST["ing"]; switch($ing) { case 'bloque': $nom=$_REQUEST["nom_blq"]; $est=$_REQUEST["est_blq"]; $result=mysql_query("insert into bloque (BLQ_NOM,BLQ_EST) values ('$nom','$est')"); break; } }else //fin del if(isset($_REQUEST["ing"])) if(isset($_REQUEST["upd"])){ //desde acá manejaremos todos los updates!! $upd=$_REQUEST["upd"]; switch($upd){ case 'bloque': $result=mysql_query("UPDATE bloque SET ".$_REQUEST['field']." = '".$_REQUEST['value']."' WHERE BLQ_IDE = ".$_REQUEST['id']); break; } } if($result){ echo "{success: true}"; }else{ $x=mysql_error(); echo "{success: false, errormsg: \"$x\"}"; }Listo, creo que con eso queda toda la parte de hacer un grid editable con filtros, si quieren ver el resultado pueden ver: <!-- m -->http://extjs.consultora-devian.net/<!-- m --> y dar click en Bloque. Espero que les sirva para empezar .. perdón por no explicarlo más en detalle pero el tiempo no me dejó ser más específico... Ahora más tarde coloco algunas dudas y problemas que se me están presentando.. <!-- s;) --><!-- s;) -->
Bueno muchachos.. he estado experimentando un poco con la parte gráfica del proyecto ya subí los cambios que he realizado y pues ya va tomado forma de proyecto "serio" jejeje. Como siempre pueden ver los cambios en <!-- m -->http://extjs.consultora-devian.net/<!-- m -->
hay algunos problemas aun que no los he podido resolver.. pero los colocaré luego cuando tenga un poco más de tiempo...
Todas sus opiniones, críticas y/o consejos como siempre serán bienvenidos..
salu2
se ve mejor!! felicidades!!
una pregunta, porque no utilizar un viewport? por que un panel estático? porque dentro del área de trabajo no hacer que los páneles ocupen todo el ancho/alto del área de trabajo?
saludos
Muchas Gracias por tus preguntas/sugerencias Stock.. en estos días trataré de aplicar lo que me dices..
aunque si me gustaría saber cuales son las grandes diferencias entre el viewport y un panel estático...
salu2
Bueno muchachos había tenido algo olvidado el proyecto pero es que el tiempo ultimamente no ha dado para mucho.. lo último que se implementó fue un botón en servicios, con el que se puede exportar el grid a un documento de excel, es soportado por firefox, opera e internet Explorer 8 (no he mirado el resto) ... ahora miraré la forma de que lo exporte a pdf...la parte gráfica aun no es la mejor.. pero después buscaré la forma de que mejore...
creo que se ha avanzado mucho desde la primera versión.. pero se que aún falta mucho.. pero poco a poco vamos avanzando.. muchas gracias por sus criticas y/u opiniones
Apenas me de un poco el tiempo haré un post explicando lo que se ha implementado y cómo se ha hecho con detalle.
Estoy terminando de subir los cambios y algunas cosas extras a la base de datos.. apenas tenga todo listo le aviso.. <!-- s;) --><!-- s;) -->
Hola crespo, mira soy nuevo con php y extjs, bueno las librerias las habia trabajado, pero unos meses(como 3 meses) y con C# en visual studio y de otra maner totalmente diferente, ya que aqui las trabajas directamente en el archivo js. Bueno mi pregunta con sobre tu proyecto como haces el treepanel como se llama ese archivo, lo qeu pasa es que lo queria ver para saber como es el evento click de cada opcion.
Saludos Daniel <!-- s:mrgreen: --><!-- s:mrgreen: -->
hola daniel.. mira que pena no responderte como mereces pero no he tenido mucho tiempo.. pero te prometo que mañana subo lo que necesitas.
un abrazo
Crespo
Hola Crespo, Como anda todo veo q muy bien, me alegro por ti, te cuento q andube algo perdido por que tuve un pequeño accidente y estuve andando con papeles de la Universidad pare empezar de una vez por todas mi proyecto de grado que de la misma manera que tu lo iré subiendo poco a poco, Si Dios quiere desde la proxima semana. Asi q ya me reincorporo para poder ver y analizar tu maravilloso poryecto.
Bueno respecto a la parte visual te puedo recomendar que lo dejes para el final del proyecto, puesto que lo principal de un sistema es q sea funcional lo q es visual después de que funcione correctamente con todos los requerimientos se podra añadir paulatinamente.
Una Pregunta Crespo Utilizaste MVC (Modelo Vista Control) . Si, no POR QUE?
o si te basaste en alguna metodología o método de desarrollo
Saludos
Hola gustavo, mira la verdad como es un proyecto para familiarizarme con el framework no le hice muy riguroso y no seguí estrictamente ningún modelo de desarrollo. Pero definitivamente para el desarrollo de tu tesis te recomendaría que sigas MVC, a mi me ha dado muy buenos resultados.
Si justamente quiero hacerlo asi, supongo q empezare el mes q viene y yo tambien creare un foro para que todos participen y ahi publicare el documento que ya entregue como primer avance en la Universidad (en si es mi perfil de grado), asi que espero que tu tambien pases por mi futuro nuevo foro saludos
Hola....
vale esta muy interesante tu proyecto yo tambien estoy incursionando con Extjs y me gustaria aprender mucho....
gracias y en lo que pueda tambien ayudare
puedes ingresar con usuario: CRESPO2 y pass:12345... aunque hace algún tiempo que no lo actualizo.. el trabajo no me deja mucha opcion para estarlo actualizando!!
el nombre de usuario es incorrecto, segun me dice tu aplicacion. ¿Podrias revisarlo y decirnos el dato correcto? De antemano gracias
Estimado crespo por problemas de cambio de hosting, me veo en la obligacion de tener q bajar tu pagina. Espero que este inconveniente sea temporal puesto q deseo seguir ayudadndo a la comunidad asi q cualquier noticia te l a comunicare.
Hola:
Estoy incursionando con extjs y recien encontre este foro, quize entrar a la pagina donde lo tienes alojado pero no pude, y segun veo esproblema de hosting, si te interesa, soy reseller, te puedo habilitar un sobdominio con base de datos y espacio que requieras de manera gratuita.
O si te interesa, tu pagas el dominio que desees (9.99 dls) y yo te lo alojo sin costo alguno, el dominio puede quedar a tu nombre, o como lo desees.
Puedes contactarme por messenger y nos ponemos de acuerdo chendo(aroba)hotmail.com o mandame un correo a <!-- e -->rgnogueda@gmail.com<!-- e -->, y levantamos el hosting de volada.
Espero tu respuesta
kchendo
muchas gracias por tu ofrecimiento, pero en estos momentos el trabajo me tiene sin mucho tiempo y no he podido avanzar en ese proyecto!! si que apenas tenga un tiempito te aviso paraque lo pongamos en linea.. y de nuevo muchas gracias por el ofrecimiento!!
Hola me llamo melisa y quería aprovechar este post para ofrecer mis [url=http://constructoresweb.com/servicios][color=#000000]servicios[/color][/url].
Trabajo hace mas de 7 años en una empresa ubicada en el norte de Argentina, provincia de Tucumán.
Allí nos dedicamos a trabajar con nuestros clientes de Europa. Yo estoy encargada de [url=http://constructoresweb.com/servicios/marketing-web-seo-sem-smo][color=#000000]SEO[/color][/url], también realizamos [url=http://constructoresweb.com/nosotros][color=#000000]desarrollos web drupal[/color][/url], [url=http://constructoresweb.com/magento][color=#000000]magento[/color][/url], etc.
Bueno, si saben de alguien o alguno necesite mis servicios me contacta por [url=http://constructoresweb.com/contacto][color=#000000]aquí[/color][/url].
Besos!!!
Hola! me llamo Paola, soy Argentina, vivo en la provincia de Tucumán y realizo
trabajos de [url=http://constructoresweb.com/drupal][color=#000000]desarrollos drupal[/color][/url], [url=http://constructoresweb.com/%20magento][color=#000000]magento[/color][/url] [url=http://constructoresweb.com/servicios/marketing-web-seo-sem-smo][color=#000000]SEO[/color][/url], diseños web, etc.
Ahora estoy mas relajada de trabajo, si necesitan los [url=http://constructoresweb.com/servicios/marketing-web-seo-sem-smo][color=#000000]servicios[/color][/url] de la empresa,
me avisan por [url=http://constructoresweb.com/contacto]este mail.[/url]
Gracias y besos a todos!
¿Conoces a alguien que pueda responder esta pregunta? Comparte el link en Twitter o Facebook
Es necesario registrarse para poder participar en el foro! Si ya tienes una cuenta puedes entrar y comentar en este foro.