- EL CONOCIMIENTO ES Y DEBE SER LIBRE -

martes, noviembre 02, 2010

PRIMEROS PASOS CON: GWT DESIGNER + SMARTGWT + PHP

GWT Designer todavía no soporta ampliamente a SmartGWT, como consecuencia de esto se siente desesperadamente lento el IDE (contrariamente a GWT que se siente más rápido).
Sin embargo, aun con sus carencias puede ayudar considerablemente en el Diseño de una Interfaz.

El ejemplo simplemente mostrara, añadirá y editara Empleados de una gran Empresa (encargada de construir un framework al estilo de Spring Roo), para conseguir con el objetivo haremos uso de”DynamicForm” una clase de SmartGwt que reducirá significativamente el código de las operaciones.

Hasta la línea 116 del código fuente (gwtDesigner.java) lo genera GWT Designer salvo la línea 49 y 116  que se añaden programáticamente “BeginGrid” y “Begin”, respectivamente. Teniendo en claro lo anterior proceda a realizar el ejemplo como se muestran en los videos-tutoriales sin olvidar las Variables Locales que deben ser convertidos en Atributos de la Clase.(dependiendo de su configuracion, por defecto GWT Designer crea los Widgets como Variables Locales)

Nota: Este ejemplo se ejecuta con: GWT 2.1, GWT Designer 8.1, SmartGWT 2.2 y  PHP 5.2.3




Qué realiza DynamicForm?
DynamicForm nos permite crear y editar un registro muy rápidamente, simplemente hay que asignarle un DataSource  al DynamicForm. DynamicForm automáticamente reconocerá los campos del DataSource asignado y se verán reflejados en un Formulario. En nuestro ejemplo creamos los Formularios “dynamicFormNuevo” y “dynamicFormEditar”
public void Begin(){
    ...
    dynamicFormNuevo.setDataSource(DSDesigner.getInstance());
    dynamicFormEditar.setDataSource(DSDesigner.getInstance());
   }
Cómo creamos un Empleado?
Antes de poder crear un Empleado será necesario validar el ingreso de datos. El método “saveData” de DynamicForm llamara automáticamente a “fetch.php”.
public void OnClickNuevo_Guardar(){
    if(dynamicFormNuevo.validate()){
     dynamicFormNuevo.saveData();
     ...
     ...
    }
   }
Cómo editamos un Empleado?
En nuestro ejemplo para poder editar un Empleado necesitamos implementar el evento “onRecordClick” de la grilla “listgrid”.
public void OnClickRecordGrid(){
    dynamicFormEditar.reset();
    dynamicFormEditar.editSelectedData(listGrid);
   }
Enseguida procedemos a validar el ingreso de datos con el método “validate”, después guardamos los cambios realizados con el método “saveData”que automáticamente llamara a “update.php”.
public void OnClickEditar_Guardar(){
    if(dynamicFormEditar.validate()){
     dynamicFormEditar.saveData();
     ...
     ...
    }
   }



/**
 * Codigo Fuente GWTDesigner
 */
public class gwtdesigner implements EntryPoint {
 private DynamicForm dynamicFormEditar;
 private Tab tabEditar;
 private Tab tabNuevo;
 private DynamicForm dynamicFormNuevo;
 private Tab tabGrilla;
 private ListGrid listGrid;
 private TabSet tabSet;
 
 public void onModuleLoad() {
  RootPanel rootPanel = RootPanel.get();
  
  tabSet = new TabSet();
  tabGrilla=new Tab("Empleados");
  
  VLayout layout = new VLayout();
  
  ToolStrip toolStrip = new ToolStrip();
  toolStrip.setSize("100%", "25px");
  
  ToolStripButton btnGrillaNuevo = new ToolStripButton("Nuevo");
  btnGrillaNuevo.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
   public void onClick(com.smartgwt.client.widgets.events.ClickEvent event) {
    OnClickGrilla_Nuevo();
   }
  });
  btnGrillaNuevo.setIcon("icons/16/new.gif");
  toolStrip.addButton(btnGrillaNuevo);
  
  ToolStripButton btnGrillaEditar = new ToolStripButton("Editar");
  btnGrillaEditar.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
   public void onClick(com.smartgwt.client.widgets.events.ClickEvent event) {
    OnClickGrilla_Editar();
   }
  });
  btnGrillaEditar.setIcon("icons/16/edit.png");
  toolStrip.addButton(btnGrillaEditar);
  layout.addMember(toolStrip);
  
  listGrid = new ListGrid();
  listGrid.addRecordClickHandler(new RecordClickHandler() {
   public void onRecordClick(RecordClickEvent event) {
    OnClickRecordGrid();
   }
  });
  BeginGrid();
  layout.addMember(listGrid);
  tabGrilla.setPane(layout);
  tabNuevo=new Tab("Nuevo");
  
  VLayout layout_1 = new VLayout();
  
  ToolStrip toolStrip_1 = new ToolStrip();
  toolStrip_1.setSize("100%", "25px");
  
  ToolStripButton btnNuevoGuardar = new ToolStripButton("Guardar");
  btnNuevoGuardar.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
   public void onClick(com.smartgwt.client.widgets.events.ClickEvent event) {
    OnClickNuevo_Guardar();
   }
  });
  btnNuevoGuardar.setIcon("icons/16/disk_blue.png");
  toolStrip_1.addButton(btnNuevoGuardar);
  
  ToolStripButton btnNuevoSalir = new ToolStripButton("Salir");
  btnNuevoSalir.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
   public void onClick(com.smartgwt.client.widgets.events.ClickEvent event) {
    OnClickNuevo_Salir();
   }
  });
  btnNuevoSalir.setIcon("icons/16/salir.png");
  toolStrip_1.addButton(btnNuevoSalir);
  layout_1.addMember(toolStrip_1);
  
  dynamicFormNuevo = new DynamicForm();
  layout_1.addMember(dynamicFormNuevo);
  tabNuevo.setPane(layout_1);
  tabEditar=new Tab("Editar");
  
  VLayout layout_2 = new VLayout();
  
  ToolStrip toolStrip_2 = new ToolStrip();
  toolStrip_2.setSize("100%", "25px");
  
  ToolStripButton btnEditarGuardar = new ToolStripButton("Guardar");
  btnEditarGuardar.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
   public void onClick(com.smartgwt.client.widgets.events.ClickEvent event) {
    OnClickEditar_Guardar();
   }
  });
  btnEditarGuardar.setIcon("icons/16/disk_blue.png");
  toolStrip_2.addButton(btnEditarGuardar);
  
  ToolStripButton btnEditarSalir = new ToolStripButton("Salir");
  btnEditarSalir.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
   public void onClick(com.smartgwt.client.widgets.events.ClickEvent event) {
    OnClickEditar_Salir();
   }
  });
  btnEditarSalir.setIcon("icons/16/salir.png");
  toolStrip_2.addButton(btnEditarSalir);
  layout_2.addMember(toolStrip_2);
  
  dynamicFormEditar = new DynamicForm();
  layout_2.addMember(dynamicFormEditar);
  tabEditar.setPane(layout_2);
  tabSet.addTab(tabGrilla);
  tabSet.addTab(tabNuevo);
  tabSet.addTab(tabEditar);
  tabSet.setSize("430px", "299px");
  rootPanel.add(tabSet, 10, 10);
  
  Begin();
 }
 /*
    * Inicio de Eventos
    */
   public void OnClickGrilla_Nuevo(){
    tabNuevo.setDisabled(false);
    tabSet.selectTab(1);
    dynamicFormNuevo.reset();
   }
   public void OnClickGrilla_Editar(){
    tabEditar.setDisabled(false);
    tabSet.selectTab(2);
   }
   public void OnClickNuevo_Guardar(){
    if(dynamicFormNuevo.validate()){
     dynamicFormNuevo.saveData();
     tabNuevo.setDisabled(true);
     tabSet.selectTab(0); 
    }
   }
   public void OnClickNuevo_Salir(){
    tabNuevo.setDisabled(true);
    tabSet.selectTab(0);
   }
   public void OnClickEditar_Guardar(){
    if(dynamicFormEditar.validate()){
     dynamicFormEditar.saveData();
     tabEditar.setDisabled(true);
     tabSet.selectTab(0);
    }
   }
   public void OnClickEditar_Salir(){
    tabEditar.setDisabled(true);
    tabSet.selectTab(0);
   }
   public void OnClickRecordGrid(){
    dynamicFormEditar.reset();
    dynamicFormEditar.editSelectedData(listGrid);
   }
   public void BeginGrid(){
       
    listGrid.setDataSource(DSDesigner.getInstance());
    //$hide>>$
    listGrid.setAutoFetchData(true);
    //$hide<<$
    ListGridField  id = new ListGridField ("id", "ID",20);
    ListGridField  nombres = new ListGridField ("nombres", "NOMBRES",100);
    ListGridField  dni = new ListGridField ("dni", "DNI",60);
    ListGridField  telefono = new ListGridField ("email", "E-MAIL");
    listGrid.setFields(id,nombres,dni,telefono);
   }
   public void Begin(){
    //$hide>>$
    tabNuevo.setDisabled(true);
    tabEditar.setDisabled(true);
    //$hide<<$
    dynamicFormNuevo.setDataSource(DSDesigner.getInstance());
    dynamicFormEditar.setDataSource(DSDesigner.getInstance());
   }
}
/**
 * Codigo Fuente DSDesigner
 */
public class DSDesigner extends RestDataSource{

 private static DSDesigner instance = null;
 
 public static DSDesigner getInstance() {
  if (instance == null) {
   instance = new DSDesigner();
  }
  return instance;
 }//end function
 
 private DSDesigner()
 {
  OperationBinding fetch = new OperationBinding();
  fetch.setOperationType(DSOperationType.FETCH);
  fetch.setDataProtocol(DSProtocol.POSTPARAMS);

  OperationBinding add = new OperationBinding();
  add.setOperationType(DSOperationType.ADD);
  add.setDataProtocol(DSProtocol.POSTPARAMS);

  OperationBinding remove = new OperationBinding();
  remove.setOperationType(DSOperationType.REMOVE);
  remove.setDataProtocol(DSProtocol.POSTPARAMS);

  OperationBinding update = new OperationBinding();
  update.setOperationType(DSOperationType.UPDATE);
  update.setDataProtocol(DSProtocol.POSTPARAMS);

  this.setOperationBindings(fetch, add, remove, update);
  this.setDataFormat(DSDataFormat.JSON);
  
  this.setFetchDataURL("fetch.php");
  this.setAddDataURL("add.php");
  this.setUpdateDataURL("update.php");
  
  DataSourceIntegerField id = new DataSourceIntegerField("id");
  id.setPrimaryKey(true); 
 
  DataSourceTextField nombres = new DataSourceTextField("nombres");
  
  RegExpValidator maskDni=new RegExpValidator();
  maskDni.setErrorMessage("dni es invalido");  
  maskDni.setExpression("[0-9]{8}");  
        
  DataSourceTextField dni = new DataSourceTextField("dni");
  dni.setValidators(maskDni);
  dni.setLength(8);
  
  RegExpValidator maskEmail=new RegExpValidator();
  maskEmail.setErrorMessage("e-mail es invalido");  
     maskEmail.setExpression("^([a-zA-Z0-9_.\-+])+@(([a-zA-Z0-9\-])+\.)+[a-zA-Z0-9]{2,4}$");  
           
  DataSourceTextField email = new DataSourceTextField("email");
  email.setValidators(maskEmail);
  
  this.setFields(id,nombres,dni,email);
  
 }//end functiono
 
}//end class
<?php
/*
* Codigo fuente de add.php
*/
$data=array();
$data[0]["id"]=$_POST["id"];
$data[0]["nombres"]=$_POST["nombres"];
$data[0]["dni"]=$_POST["dni"];
$data[0]["email"]=$_POST["email"];
 
$mensaje=array();
$mensaje["response"]["status"]=0;
$mensaje["response"]["data"]=$data;
 
echo json_encode($mensaje);
?>
<?php
/*
* Codigo fuente de fetch.php
*/
$data=array();
$data[0]["id"]=1;
$data[0]["nombres"]="Sanjiv Jivans";
$data[0]["dni"]="86763232";
$data[0]["email"]="sanjiv@smartgwt.com";
 
$data[1]["id"]=2;
$data[1]["nombres"]="Eric Clayberg";
$data[1]["dni"]="89328745";
$data[1]["email"]="eric@gwtdesigner.com";
 
$data[2]["id"]=3;
$data[2]["nombres"]="Fabien Potencier";
$data[2]["dni"]="84563245";
$data[2]["email"]="fabien@symfony.com";
 
$mensaje=array();
$mensaje["response"]["status"]=0;
$mensaje["response"]["data"]=$data;
 
echo json_encode($mensaje);
?>
<?php
/*
* Codigo fuente de update.php
*/
$data=array();
$data[0]["id"]=$_POST["id"];
$data[0]["nombres"]=$_POST["nombres"];
$data[0]["dni"]=$_POST["dni"];
$data[0]["email"]=$_POST["email"];
 
$mensaje=array();
$mensaje["response"]["status"]=0;
$mensaje["response"]["data"]=$data;
 
echo json_encode($mensaje);
?>

16 comentarios:

Anónimo dijo...

Hola!

Antes que todo gracias por el todo el aporte que haces con tu página... me ha sido muy útil y seguramente que a muchos otros tambien.

Tal vez puedes ayudarme porque hice todo el tutorial de Blogspot y GWTDesigner y en ambos tengo el mismo problema... cuando ejecuto la aplicación el ListGrid dice "Loading Data..." y nunca aparecen las filas que están en el fetch.php

Me aparece un error en Eclipse que dice:

RestDataSource_RestDataSource_0:Error evaluating JSON: SyntaxError: Unexpected token <, JSON text:

Tienes idea de qué puede ser??

Muchas gracias.

Jorge Cotrado dijo...

Acabo de ejecutar el ejemplo y no tuve ningun problema.... lo que se me ocurre sq tal vez la codificacion de caracteres (text file encoding)del ide eclipse no esta en UTF-8.

Salu2

Erick dijo...

A mí tambien me sale un error, el formulario se queda con la leyenda "Loading data" el error es: [ERROR] [pck.gwtDesigner] 14:45:19.243:XRP4:WARN:RestDataSource:isc_DSDesigner_0:Error evaluating JSON: SyntaxError: Syntax error, JSON text: todo el código php

Jorge Cotrado dijo...

Te olvidas de crear un HOST-VIRTUAL
en el video se muestra como configurar el IDE de Eclipse para levantar el host-virtual(previamente creado).Revisa el siguiente post:
http://jumanor.blogspot.com/2010/05/ejecutar-y-depurar-gwt-sobre-el.html

Salu2

favrycio dijo...

Como recibes la respuesta despues de mandar a grabar. Como recibes estos valores:

$mensaje["response"]["status"]=0;
$mensaje["response"]["data"]=$data;

Jorge Cotrado dijo...

No entiendo tu consulta... se mas claro

Salu2

Jorge Cotrado dijo...

Espero esto clarifique el panorama:

http://www.smartclient.com/smartgwt/javadoc/com/smartgwt/client/data/RestDataSource.html

Salu2

favrycio dijo...

Hola,

Al mandar a grabar al php tu tienes:



Como o donde recibes este mensaje echo json_encode($mensaje);

Gracias por tus respuestas, salu2

Jorge Cotrado dijo...

En la DataSource en la linea 36 de "DSDesigner.java"

this.setFetchDataURL("fetch.php");
this.setAddDataURL("add.php");
this.setUpdateDataURL("update.php");

Salu2

Unknown dijo...

Hola Buenas Tardes, ¿Como puedo conectarme y hacer consultas a un servidor MySql desde SmartGWT?

XeNeIzE dijo...

Por lo que estuve leyendo en los foros de SmartGWT y demás, es necesario escribir uno su propio código o métodos para hacer conexión con MySQL. Es por eso que no se encuentran demasiados ejemplos. Éste es el caso, claro, para quienes utilizan la versión FREE.

Para aquellos que tengan la posibilidad de comprar las versiones de SmartGWT EE Pro o Enterprise, pueden utilizar las herramientas visuales que les proporciona para conectarse fácilmente a distintos tipos de servidores. Lamentablemente no es nada barato.

Claro que es posible conectarse y hacer consultas a MySQL, pero es necesario codificar un "puente" para hacer esto.

Una manera de hacerlo es desarrollar un PHP que se conecte a la base de datos. Luego, a través de GWT, conectarse al PHP para hacer consultas utilizando los métodos necesarios.

Jorge Cotrado dijo...

Quiero añadir, que no es necesario desarrollar codigo PHP para conectarse a la BD; ya que, esto lo la hace normalmente un ORM (Doctrine ORM)

Anónimo dijo...

All can be

Malabash dijo...

Sólo quería agradecerte por esta información. Realmente nos abres muchas puertas con ésto.
Muchas gracias!

Unknown dijo...

En el wiki público SmartGWT, hay una serie de artículos que muestran cómo construir código servidor con PHP para RestDataSource, que soporta las 4 operaciones básicas(crear, recuperar, actualizar y eliminar), incluyendo commits transaccionales y con AdvancedCriteria a la base de datos(utilizando la libreria PHP RedBean). Puede verlos acqui:

http://wiki.smartclient.com/display/Main/Integrating+with+PHP

Unknown dijo...

En el wiki público SmartGWT, hay una serie de artículos que muestran cómo construir código servidor con PHP para RestDataSource, que soporta las 4 operaciones básicas(crear, recuperar, actualizar y eliminar), incluyendo commits transaccionales y con AdvancedCriteria a la base de datos(utilizando la libreria PHP RedBean). Puede verlos acqui:

http://wiki.smartclient.com/display/Main/Integrating+with+PHP