Creating a Database-driven Application"

From Documentation
m
 
(29 intermediate revisions by 4 users not shown)
Line 1: Line 1:
 +
{{ZK_5_Needs_Translating
 +
| page=[[ZK_Getting_Started/Creating_a_Database-driven_Application#Running_the_sample_application_without_an_IDE | tutorial]]
 +
| language=Spanish
 +
|}}
 +
 
Translated by '''Sergio Cerro Pascual'''
 
Translated by '''Sergio Cerro Pascual'''
 +
=Before You Start=
 +
 +
Translations are available in [[ZK_Getting_Started/Creating a Database-driven Application|English]], [[ZK_Getting_Started_fr/Creating a Database-driven Application|Français]], [[ZK_Getting_Started_es/Creating a Database-driven Application|Español]], [[ZK_Getting_Started_it/Creating a Database-driven Application|Italiano]] and [http://jp.zkoss.org/doc/tutorial-jp.dsp 日本語].
 +
 +
'''Other Introductions'''
 +
 +
* [[ZK_Getting_Started/Tutorial|Tutorial]] - A brief tutorial guides you through the most fundamental features and concepts of ZK.
 +
* [[ZK_Installation_Guide_es/Quick_Start/Create_and_Run_Your_First_ZK_Application_with_Eclipse_and_ZK_Studio|Creating Hello World with Eclipse and ZK Studio]] - Step by step to create a Web application from scratch with Eclipse and [http://www.zkoss.org/product/zkstudio.dsp ZK Studio].
 +
* [[ZK_Getting_Started/Creating a Simple Sightseeing Application|Creating a simple sightseeing application]] - A tutorial exploring some of ZK's key elements by creating a sightseeing application without using database
 +
* [[ZK Essentials]] - A book which walks you through the key concepts and features by building a working application from the ground up.
  
 
= Un ejemplo real usando una base de datos=
 
= Un ejemplo real usando una base de datos=
Line 71: Line 86:
  
 
<source lang="java">
 
<source lang="java">
public class ToDoEvent {
+
public class TodoEvent {
  private String id;
+
    private String id;
  private String name;
+
    private String name;
  private int priority;
+
    private int priority;
  private Date date;
+
    private Date date;
  
  public ToDoEvent(){}
+
    public TodoEvent(String id, String name, int priority, Date date) {
  public ToDoEvent(String id,String name,int priority,Date date){
+
        this.id = id;
  this.id = id;
+
        this.name = name;
  this.name = name;
+
        this.priority = priority;
  this.priority = priority;
+
        this.date = date;
  this.date = date;
+
    }
  }
+
 
  //Los métodos getter y setter están omitidos. Por favor consulta el código fuente.
+
    // getter and setter methods are ommited, please refer to the source code.
}
+
}
 
</source>
 
</source>
  
Line 92: Line 107:
  
 
<source lang="java">
 
<source lang="java">
public class EventDAO {
+
public class EventDAO {
  private String url = "jdbc:hsqldb:file:/hsqldb/event";
+
     // The implementation is ommited, please refer to the source code.
  private String user = "sa";
+
public List<TodoEvent> findAll() {
  private String pwd = "";
+
}
 
+
  public EventDAO() {
+
public boolean delete(TodoEvent evt) {
  try {
+
}
    Class.forName("org.hsqldb.jdbcDriver");
+
  } catch (ClassNotFoundException e) {
+
public boolean insert(TodoEvent evt) {
     e.printStackTrace();
+
}
  }
+
  }
+
public boolean update(TodoEvent evt) {
  // La implementación está omitida, por favor consulta el código fuente.
+
    }
  public List findAll(){}  
+
}
  public boolean delete(ToDoEvent evt){}  
 
  public boolean insert(ToDoEvent evt){}  
 
  public boolean update(ToDoEvent evt){}
 
  }
 
 
</source>
 
</source>
  
Line 120: Line 131:
  
  
<source lang="xml"><window title="To do list" width="640px" border="normal">
+
<source lang="xml">
</window></source>
+
<window title="To do list" border="normal">
 +
</window>
 +
</source>
  
  
Line 131: Line 144:
 
Lo siguiente, vamos a intentar enriquecer esta página con más componentes ZK. Para mostrar datos en una tabla, podemos usar un componente &nbsp;listbox&nbsp; el cual está diseñado para mostrar datos. Para insertar un listbox lo declaramos dentro de los tags del componente &nbsp;window&nbsp;, como se indica:
 
Lo siguiente, vamos a intentar enriquecer esta página con más componentes ZK. Para mostrar datos en una tabla, podemos usar un componente &nbsp;listbox&nbsp; el cual está diseñado para mostrar datos. Para insertar un listbox lo declaramos dentro de los tags del componente &nbsp;window&nbsp;, como se indica:
 
<source lang="xml">
 
<source lang="xml">
  <window title="To do list" width="640px" border="normal">
+
  <window title="To do list" border="normal">
   <listbox id="box" multiple="true" rows="4">
+
   <listbox id="box" multiple="true" rows="5">
  </listbox>
+
  </listbox>
 
  </window>
 
  </window>
 
</source>
 
</source>
Line 144: Line 157:
  
 
<source lang="xml">
 
<source lang="xml">
<window title="To do list" width="640px" border="normal">
+
<window id="win" title="To do list" width="640px" border="normal">
  <listbox id="box" multiple="true" rows="4">
+
<listbox id="box" multiple="true" rows="5">
  <listhead>
+
<listhead>
    </listhead>
+
</listhead>
    <listitem>
+
<listitem>
    </listitem>
+
</listitem>
  </listbox>
+
</listbox>
</window>
+
</window>
 
</source>
 
</source>
  
 
Aún no hemos terminado. Vamos a declarar tres componentes listheader dentro de los tags de listhead. Necesitamos tres columnas -- 「Item」, 「Priority」, and 「Date」 -- dentro de la tabla, como se indica:
 
Aún no hemos terminado. Vamos a declarar tres componentes listheader dentro de los tags de listhead. Necesitamos tres columnas -- 「Item」, 「Priority」, and 「Date」 -- dentro de la tabla, como se indica:
 
<source lang="xml">
 
<source lang="xml">
<window title="To do list" width="640px" border="normal">
+
<window id="win" title="To do list" width="640px" border="normal">
<listbox id="box" multiple="true" rows="4">
+
<listbox id="box" multiple="true" rows="5">
  <listhead>
+
<listhead>
      <listheader label="Item" sort="auto"/>
+
<listheader label="Item" />
      <listheader label="Priority" width="60px" sort="auto"/>
+
<listheader label="Priority" width="80px" />
      <listheader label="Date" width="90px" sort="auto"/>
+
<listheader label="Date" width="170px" />
  </listhead>
+
</listhead>
  <listitem>
+
<listitem>
  </listitem>
+
</listitem>
  </listbox>
+
</listbox>
</window>
+
</window>
 
</source>
 
</source>
  
Line 174: Line 187:
  
 
<source lang="xml">
 
<source lang="xml">
<window title="To do list" width="640px" border="normal">
+
<window id="win" title="To do list" width="640px" border="normal">
<listbox id="box" multiple="true" rows="4">
+
<listbox id="box" multiple="true" rows="5">
  <listhead>
+
<listhead>
    <listheader label="Item" sort="auto"/>
+
<listheader label="Item" />
    <listheader label="Priority" width="60px" sort="auto"/>
+
<listheader label="Priority" width="80px" />
    <listheader label="Opened" width="90px" sort="auto"/>
+
<listheader label="Date" width="170px" />
  </listhead>
+
</listhead>
  <listitem>
+
<listitem>
      <listcell/>
+
<listcell />
      <listcell/>
+
<listcell />
      <listcell/>
+
<listcell />
  </listitem>
+
</listitem>
  </listbox>
+
</listbox>
</window>
+
</window>
 
</source>
 
</source>
  
 
La estructura anidada del componente &nbsp;listbox&nbsp; quedaría así,
 
La estructura anidada del componente &nbsp;listbox&nbsp; quedaría así,
  
  +listbox  
+
  listbox  
  +listhead
+
+-- listhead
      listheader
+
|    |
  +listitem
+
|    +-- listheader
       listcell
+
|
 +
+-- listitem
 +
       |
 +
      +-- listcell
  
 
== Componentes para introducir información ==
 
== Componentes para introducir información ==
Line 202: Line 218:
  
 
<source lang="xml">
 
<source lang="xml">
<window title="To do list" width="640px" border="normal">
+
<window id="win" title="To do list" width="640px" border="normal">
<listbox id="box" multiple="true" rows="4">
+
<listbox id="box" multiple="true" rows="5">
  <listhead>
+
<listhead>
    <listheader label="Item" sort="auto"/>
+
<listheader label="Item" />
    <listheader label="Priority" width="60px" sort="auto"/>
+
<listheader label="Priority" width="80px" />
    <listheader label="Opened" width="90px" sort="auto"/>
+
<listheader label="Date" width="170px" />
  </listhead>
+
</listhead>
  <listitem>
+
<listitem>
    <listcell/>
+
<listcell />
    <listcell/>
+
<listcell />
    <listcell/>
+
<listcell />
  </listitem>
+
</listitem>
  </listbox>
+
</listbox>
  Item:<textbox id="name" cols="50" />
+
Item: <textbox id="name" cols="25" />
    Priority:<intbox id="priority" cols="1" />
+
Priority: <intbox id="priority" cols="1" />
    Date:<datebox id="date" cols="8" />
+
Date: <datebox id="date" cols="8" />
    <button label="Add" width="36px" height="24px"/>
+
<button id="add" label="Add" />
    <button label="Update" width="46px" height="24px"/>
+
<button id="update" label="Update" />
    <button label="Delete" width="46px" height="24px"/>  
+
<button id="delete" label="Delete" />
</window>
+
</window>
 
</source>
 
</source>
  
Line 228: Line 244:
  
 
<source lang="xml">
 
<source lang="xml">
<window title="To do list" width="640px" border="normal">
+
<window id="win" title="To do list" width="640px" border="normal">
<listbox id="box" multiple="true" rows="4">
+
<listbox id="box" multiple="true" rows="5">
  <listhead>
+
<listhead>
    <listheader label="Item" sort="auto"/>
+
<listheader label="Item" />
    <listheader label="Priority" width="60px" sort="auto"/>
+
<listheader label="Priority" width="80px" />
    <listheader label="Opened" width="90px" sort="auto"/>
+
<listheader label="Date" width="170px" />
  </listhead>
+
</listhead>
  <listitem>
+
<listitem>
    <listcell/>
+
<listcell />
    <listcell/>
+
<listcell />
    <listcell/>
+
<listcell />
  </listitem>
+
</listitem>
  </listbox>
+
</listbox>
    <groupbox>
+
<groupbox>
        <caption label="Event" />
+
<caption label="Event" />
        Item: <textbox id="name" cols="50" />
+
Item: <textbox id="name" cols="25" />
        Priority: <intbox id="priority" cols="1" />
+
Priority: <intbox id="priority" cols="1" />
        Date: <datebox id="date" cols="8" />
+
Date: <datebox id="date" cols="8" />
        <button label="Add" width="36px" height="24px"/>
+
<button id="add" label="Add" />
        <button label="Update" width="46px" height="24px"/>
+
<button id="update" label="Update" />
        <button label="Delete" width="46px" height="24px"/>
+
<button id="delete" label="Delete" />
    </groupbox>
+
</groupbox>
</window>
+
</window>
 
</source>
 
</source>
  
Line 265: Line 281:
  
 
<source lang="java">
 
<source lang="java">
org.zkforge.todo.event.EventController.java
+
// org.zkforge.todo.event.EventController.java
  
 
public class EventController extends GenericForwardComposer {
 
public class EventController extends GenericForwardComposer {
EventDAO evtdao = new EventDAO();
+
    private static final long serialVersionUID = -9145887024839938515L;
+
    private EventDAO eventDao = new EventDAO();
public List getAllEvents() {
+
 
return evtdao.findAll();
+
    // Note: Something is omitted at here. You can view detail about this class on source code.
}
+
 
public void addEvent() {}
+
    public List<TodoEvent> getAllEvents() {
public void updateEvent() {}
+
        return eventDao.findAll();
public void deleteEvent() {}
+
    }
 +
 
 +
    public void onClick$add() {
 +
    }
 +
 
 +
    public void onClick$update() {
 +
    }
 +
 
 +
    public void onClick$delete() {
 +
    }
 
}
 
}
 
</source>
 
</source>
Line 283: Line 308:
 
Para implmentar la interacción entre la Vista y el Controlador asignamos el atributo '''apply''' al componente '''window''' en la ruta de nuestro '''EventController'''.
 
Para implmentar la interacción entre la Vista y el Controlador asignamos el atributo '''apply''' al componente '''window''' en la ruta de nuestro '''EventController'''.
  
<source lang="xml">
+
<source lang="xml" high="2">
<window id="win" title="To do list" width="640px" border="normal" apply="org.zkforge.todo.event.EventController">
+
<window id="win" title="To do list" width="640px" border="normal"
 +
apply="org.zkforge.todo.event.EventController">
  
 +
......
 
</source>
 
</source>
  
Line 297: Line 324:
  
 
=== Activando el mecanismo de DataBinding ===
 
=== Activando el mecanismo de DataBinding ===
Para usar el mecanismo[[ZK_Developer's_Guide/ZK_in_Depth/Data_Binding|DataBinding]], deberemos activar el Data Binding Manager ('''org.zkoss.zkplus.databind.AnnotateDataBinderInit''') en la parte superior de la página.
+
Para usar el mecanismo[[ZK Developer's Reference/Data Binding|Data Binding]], deberemos activar el Data Binding Manager ('''org.zkoss.zkplus.databind.AnnotateDataBinderInit''') en la parte superior de la página.
<source lang="xml">
+
<source lang="xml" high="1">
 
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit"?>
 
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit"?>
  
<window id="win" title="To do list" width="640px" border="normal" apply="org.zkforge.todo.event.EventController">
+
<window id="win" title="To do list" width="640px" border="normal"
 +
apply="org.zkforge.todo.event.EventController">
 
....
 
....
 
</source>
 
</source>
Line 309: Line 337:
  
  
<source lang="xml">
+
<source lang="xml" high="3">
<window id="win" title="To do list" width="640px" border="normal" apply="org.zkforge.todo.event.EventController">
+
<window id="win" title="To do list" width="640px" border="normal"
 +
apply="org.zkforge.todo.event.EventController">
 
<listbox id="box" multiple="true" rows="5" model="@{win$composer.allEvents}">
 
<listbox id="box" multiple="true" rows="5" model="@{win$composer.allEvents}">
 
....
 
....
Line 320: Line 349:
 
Esto se logra gracias a la utilización de los atributos que ofrece el componente "listitem" definiendo una varible para representar cada instancia a reflejar.  
 
Esto se logra gracias a la utilización de los atributos que ofrece el componente "listitem" definiendo una varible para representar cada instancia a reflejar.  
  
<source lang="xml">
+
<source lang="xml" high="12, 13, 14">
<window id="win" title="To do list" width="640px" border="normal" apply="org.zkforge.todo.event.EventController">
+
<window id="win" title="To do list" width="640px" border="normal"
<listbox id="box" multiple="true" rows="5" model="@{win$composer.allEvents}">
+
apply="org.zkforge.todo.event.EventController">
 +
<listbox id="box" multiple="true" rows="5"
 +
    model="@{win$composer.allEvents, load-after='add.onClick, delete.onClick, update.onClick'}"
 +
    selectedItem="@{win$composer.current}">
 
<listhead>
 
<listhead>
<listheader label="Item" sort="auto"/>
+
<listheader label="Item" sort="auto(name)" />
<listheader label="Priority" width="60px" sort="auto"/>
+
<listheader label="Priority" width="80px" sort="auto(priority)" />
<listheader label="Date" width="90px" sort="auto"/>
+
<listheader label="Date" width="170px" sort="auto(date)" />
</listhead>
+
</listhead>
<listitem self="@{each='event'}" value="@{event}">
+
<listitem self="@{each='event'}" value="@{event}">
 
<listcell label="@{event.name}" />
 
<listcell label="@{event.name}" />
 
<listcell label="@{event.priority}" />
 
<listcell label="@{event.priority}" />
Line 336: Line 368:
 
</source>
 
</source>
  
Para más información, por favor dirígete a [[ZK_Developer's_Guide/ZK_in_Depth/Data_Binding/Associate_UI_Components_with_a_Collection|Associate UI Components with a Collection]].
+
Para más información, por favor dirígete a [[ZK Developer's Reference/Data Binding/Associate UI Components with a Collection|Associate UI Components with a Collection]].
  
 
== Sincronización de vistas ==
 
== Sincronización de vistas ==
 
Una vez el usuario selecciona un ToDoEvent en el '''listbox''', Necesitamos mostrarlo en el componente '''groupbox'''  también. Sería mucho mejor si este tedioso trabajo fuera realizado de forma automáticamente.
 
Una vez el usuario selecciona un ToDoEvent en el '''listbox''', Necesitamos mostrarlo en el componente '''groupbox'''  también. Sería mucho mejor si este tedioso trabajo fuera realizado de forma automáticamente.
[[ZK_Developer's_Guide/ZK_in_Depth/Data_Binding|DataBinding]] es la respuesta! Simplemente asocia los datos con todo lo relacionado con los componentes de UI. El DataBinding se sincronizará entonces con todos los componentes de Interfaz de Usuario una vez la propiedad ha sido modificada.
+
[[ZK Developer's Reference/Data Binding|Data Binding]] es la respuesta! Simplemente asocia los datos con todo lo relacionado con los componentes de UI. El DataBinding se sincronizará entonces con todos los componentes de Interfaz de Usuario una vez la propiedad ha sido modificada.
 
*[[#Definir una instancia en un Controlador|Definir una instancia en un Controlador]]
 
*[[#Definir una instancia en un Controlador|Definir una instancia en un Controlador]]
 
*[[#Asociar multiples componentes UI a la instancia|Asociar multiples componentes UI a la instancia]]
 
*[[#Asociar multiples componentes UI a la instancia|Asociar multiples componentes UI a la instancia]]
Line 347: Line 379:
 
Define una instnacia '''ToDoEvent'''  en ''EventController''', y define métodos getter y setter para que puedan ser accesibles desde la vista.
 
Define una instnacia '''ToDoEvent'''  en ''EventController''', y define métodos getter y setter para que puedan ser accesibles desde la vista.
  
<source lang="java">
+
<source lang="java" high="4, 6, 10">
org.zkforge.todo.event.EventController.java
+
// org.zkforge.todo.event.EventController.java
  
 
public class EventController extends GenericForwardComposer {
 
public class EventController extends GenericForwardComposer {
....
+
    private TodoEvent current = new TodoEvent();
ToDoEvent current = new ToDoEvent();
+
    // Omitted...
public ToDoEvent getCurrent() {
+
    public TodoEvent getCurrent() {
return current;
+
        return current;
}
+
    }
public void setCurrent(ToDoEvent current) {
+
 
this.current = current;
+
    public void setCurrent(TodoEvent current) {
}
+
        this.current = current;
....
+
    }
}
 
 
</source>
 
</source>
  
 
===Asociando múltiples componentes UI con la instancia EventController ===
 
===Asociando múltiples componentes UI con la instancia EventController ===
 
Primero, asocia la instancia EventController con la propiedad '''selectedItem''' del  '''listbox'''. Después, asocia las propiedades del '''ToDoEvent'''  con el correspondiente componentes UI, incluyendo '''textbox''', '''intbox''', y '''datebox'''. Una vez el usuario selecciona un item en un '''listbox''', la instnacia se actualizará en relación a los componentes UI.
 
Primero, asocia la instancia EventController con la propiedad '''selectedItem''' del  '''listbox'''. Después, asocia las propiedades del '''ToDoEvent'''  con el correspondiente componentes UI, incluyendo '''textbox''', '''intbox''', y '''datebox'''. Una vez el usuario selecciona un item en un '''listbox''', la instnacia se actualizará en relación a los componentes UI.
<source lang="xml">
+
<source lang="xml" start="4" high="6, 10, 11, 12">
<listbox id="box" multiple="true" rows="5" model="@{win$composer.allEvents}"  
+
<listbox id="box" multiple="true" rows="5"
selectedItem="@{win$composer.current}">
+
      model="@{win$composer.allEvents, load-after='add.onClick, delete.onClick, update.onClick'}"  
....
+
      selectedItem="@{win$composer.current}">
<groupbox>
+
<!-- Omitted -->
 +
<groupbox>
 
<caption label="Event" />
 
<caption label="Event" />
 
Item: <textbox id="name" cols="25" value="@{win$composer.current.name}" />
 
Item: <textbox id="name" cols="25" value="@{win$composer.current.name}" />
 
Priority: <intbox id="priority" cols="1" value="@{win$composer.current.priority}" />
 
Priority: <intbox id="priority" cols="1" value="@{win$composer.current.priority}" />
 
Date: <datebox id="date" cols="8" value="@{win$composer.current.date}" />
 
Date: <datebox id="date" cols="8" value="@{win$composer.current.date}" />
....
 
 
</source>
 
</source>
  
Line 387: Line 418:
  
 
Para monitorizar la actividad del usuario, simplente registrarmos un evento listener '''onClick''' en los siguientes tres botones ''add''', '''update''' and '''delete'''. Cuando cliqueamos en estos botones que se corresponden a los métodos definidos en '''EventController''' estos serán invocados. Estos métodos son definidos así:
 
Para monitorizar la actividad del usuario, simplente registrarmos un evento listener '''onClick''' en los siguientes tres botones ''add''', '''update''' and '''delete'''. Cuando cliqueamos en estos botones que se corresponden a los métodos definidos en '''EventController''' estos serán invocados. Estos métodos son definidos así:
<source lang="java">
+
<source lang="java" high="4, 15, 22">
....
+
public class EventController extends GenericForwardComposer {
        public void onClick$add() {
+
    private EventDAO eventDao = new EventDAO();
// insert into database
+
    // Omitted...
TodoEvent newEvt = new TodoEvent(UUID.randomUUID().toString(), current.getName(),
+
    public void onClick$add() {
current.getPriority(), current.getDate());
+
        if (current != null) {
evtdao.insert(newEvt);
+
            current.setId(UUID.randomUUID().toString());
}
+
           
public void onClick$update() {
+
            if (validate(current)) {
if (box.getSelectedItem() != null) {
+
                // insert into database
// update database
+
                eventDao.insert(current);
evtdao.update((TodoEvent) box.getSelectedItem().getValue());
+
            }
}
+
        }
}
+
    }
public void onClick$delete() {
+
 
if (box.getSelectedItem() != null) {
+
    public void onClick$update() {
evtdao.delete((TodoEvent) box.getSelectedItem().getValue());
+
        if (current != null && validate(current)) {
}
+
            // update database
}....
+
            eventDao.update(current);
 +
        }
 +
    }
 +
 
 +
    public void onClick$delete() {
 +
        if (current != null && validate(current)) {
 +
            eventDao.delete(current);
 +
        }
 +
    }
 +
}
 
</source>
 
</source>
  
 
<source lang="xml">
 
<source lang="xml">
<button id="add" label="Add" width="36px" height="24px" />
+
<button id="add" label="Add" />
<button id="update" label="Update" width="46px" height="24px" />
+
<button id="update" label="Update" />
<button id="delete" label="Delete" width="46px" height="24px" />
+
<button id="delete" label="Delete" />
 
</source>
 
</source>
  
Line 417: Line 457:
 
Después de interactuar con la base de datos, el último paso es actualizar la vista. Simplemente notificar al Databinding para que actualice el modelo por ti, cuando el usuario cliquée en cualquier botón. Intenta registrar un atributo '''load-after''' en el atributo '''model''' del '''listbox''', y el Databinding actualizará la vista automáticamente si el evento especificado es capturado.
 
Después de interactuar con la base de datos, el último paso es actualizar la vista. Simplemente notificar al Databinding para que actualice el modelo por ti, cuando el usuario cliquée en cualquier botón. Intenta registrar un atributo '''load-after''' en el atributo '''model''' del '''listbox''', y el Databinding actualizará la vista automáticamente si el evento especificado es capturado.
  
<source lang="xml">
+
<source lang="xml" high="6">
 
 
 
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit"?>
 
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit"?>
  
Line 424: Line 463:
 
  apply="org.zkforge.todo.event.EventController">
 
  apply="org.zkforge.todo.event.EventController">
 
<listbox id="box" multiple="true" rows="5"
 
<listbox id="box" multiple="true" rows="5"
model="@{win$composer.allEvents, load-after='add.onClick, delete.onClick, update.onClick'}"
+
    model="@{win$composer.allEvents, load-after='add.onClick, delete.onClick, update.onClick'}"  
selectedItem="@{win$composer.current}">
+
    selectedItem="@{win$composer.current}">
.....
+
<!-- Omitted... -->
<button id="add" label="Add" width="36px" height="24px"/>
+
<button id="add" label="Add" />
<button id="update" label="Update" width="46px" height="24px"/>
+
<button id="update" label="Update" />
<button id="delete" label="Delete" width="46px" height="24px"/>
+
<button id="delete" label="Delete" />
 
</groupbox>
 
</groupbox>
 
</window>
 
</window>
Line 435: Line 474:
  
 
----
 
----
Last Update : {{REVISIONYEAR}}/{{REVISIONMONTH}}/{{REVISIONDAY}}
+
{{LastUpdated}}

Latest revision as of 10:01, 10 February 2012

WarningTriangle-32x32.png This page is for ZK 5 and is out of date. If you are interested in translating our tutorial into Spanish please contact us.

Translated by Sergio Cerro Pascual

Before You Start

Translations are available in English, Français, Español, Italiano and 日本語.

Other Introductions

Un ejemplo real usando una base de datos

Te mostraremos, paso a poaso, como construir una sencilla aplicación web que use una base de datos. Este tutorial va dirigido a nuevos usuarios de ZK, pero se requiere que el usuario tenga, al menos, una pequeña experiencia con Java. No te preocupes si no conoces otros lenguajes, Java es todo lo que necesitas en cuanto al desarrollo de Ajax en aplicaciones web con ZK.

En este tutorial, asumimos que ya tienes instalado  JDK (1.4 o superior), y un contenedor de servlets (ex.Tomcat). Si no has configurado tu entorno aún, pero estás interesado en continuar con este tutorial, te recomendamos leer Create and Run Your First ZK Application with Eclipse and ZK Studio!

Tu primera aplicación ZK. Una lista "To-do"

Imaginemos que para que nuestro día esté mejor planificado, necesitamos una aplicación web que almacene sucesos que vamos a hacer en el futuro. Una aplicación web así, requeriría usar una base de datos. Para la conclusión de este turorial usaremos una base de datos Java (HSQL DB) la cual no requiere que instalemos un servidor de base de datos. Puedes ver una demo de la aplicación en aquí.

Descargar el fichero Todo de ZK

  1. Descargar zk-todo-0.9.zip.
  2. Descomprimir zk-todo-0.9.zip, el zip contiene los siguientes ficheros y carpetas todo.war, hsqldb,readme.txt.

Ejecutando la aplicación de ejemplo sin un IDE

  1. Copia la carpeta hsqldb' al directorio raiz donde instalaste el Apache Tomcat. (ex.C:\)
  2. Copia todo.war en el directorio $TOMCAT_HOME\webapps.
  3. Inicia Apache Tomcat.
  4. Abre tu navegador y navega hasta http://localhost:8080/todo.

Ejecutando la aplicación de ejemplo con un IDE

  1. Copia la carpeta hsqldb en el directorio raiz donde se encuentra el workspace de tu eclipse. (ex.C:\).
  2. Arranca Eclipse.
  3. Selecciona Archivo > Importar .
  4. En la ventana de diálogo de la opción "Importar", selecciona Web > WAR file y después haz click siguiente.
  5. Localiza el fichero todo.war y seleccionalo (como fichero WAR para ser importado).
  6. Haz Click en Terminar para importar el proyecto web.
  7. Hz click con el botón derecho en todo en el proyecto y selecciona Ejecutar como > ejecutar en servidor
  8. Selecciona Apache > Tomcat v6.0 Server en la ventana de diálogo y haz click en Terminar
  9. Un navegador emergerá automáticamente para ejecutar el ejemplo del proyecto web "todo".

Todo.png

Todos los Escenarios

  • Introduce toda la información relativa a un evento y presiona el botón  Add  para insertarlo en la base de datos.
  • Selecciona cualquier fila en la tabla para mostrar la información del evento en los campos de abajo para que modificar su información, después presiona el botón  Update  para modificar la información.
  • Selecciona cualquier fila en la tabla y presiona el botón  Delete  para eliminar el "Event" seleccionado.

Modelo

En los siguientes párrafos, el esque de la base de datos, el objeto del dominio y el objeto DAO será introducido.

Esquema de la base de datos

Una tabla de la base de datos la cual va a almacenar los datos de nuestra aplicación, necesitará los siguientes atributos: event id, event name, event priority and event date.

El esquema de base de datos está listado abajo.

Field Type
id varchar(50)
name varchar(50)
priority int
date date

Objeto Dominio

Para la la tabla de arriba, creamos el objeto de dominio correspondiente, como se indica:

public class TodoEvent {
    private String id;
    private String name;
    private int priority;
    private Date date;

    public TodoEvent(String id, String name, int priority, Date date) {
        this.id = id;
        this.name = name;
        this.priority = priority;
        this.date = date;
    }

    // getter and setter methods are ommited, please refer to the source code.
}

Objeto de Acceso a Datos

Para que fácilmente se acceda a nuestra base de datos necesitaremos un objeto DAO con los siguientes métodos: findAll(),delete(),insert() and update().

public class EventDAO {
    // The implementation is ommited, please refer to the source code.
	public List<TodoEvent> findAll() {
	}
	
	public boolean delete(TodoEvent evt) {
	}
	
	public boolean insert(TodoEvent evt) {
	}
	
	public boolean update(TodoEvent evt) {
    }
}

La Vista

Tu primera componente ZK

El primer paso es crear un fichero el cuya extensión debe ser zul, pongamos todo.zul, y situamos este fichero bajo el directorio de nuestra aplicación web, por ejemplo, $TOMCAT_HOME/webapps/ProjectName/. Declaras un componente ZK de igual forma a como declaras un componente usando HTML.


Prueba a declarar tu primer componente  window  de la siguiente forma:


<window title="To do list" border="normal">
</window>


Después inicia Tomcat y usa el navegador para visitar la página, eg. http://localhost:8080/todo/todo.zul. El resultado se muestra abajo,  window  con el título 「To do List」.

Todo en ZK es un componente. Puedes cambiar el título, el alto y el borde de tu  window  Es muy sencillo e intuitivo. Intenta cambiar estos atributos y comprueba el resultado.

Relacciones jerárquicas entre los componentes de ZK

Lo siguiente, vamos a intentar enriquecer esta página con más componentes ZK. Para mostrar datos en una tabla, podemos usar un componente  listbox  el cual está diseñado para mostrar datos. Para insertar un listbox lo declaramos dentro de los tags del componente  window , como se indica:

 <window title="To do list" border="normal">
  <listbox id="box" multiple="true" rows="5">
  </listbox>
 </window>

En este ejemplo, el componente  listbox  es un componente hijo de  window. Sí, hay relacciones jerárquicas entre los componentes de ZK, te encontrarás una excepción UI si intentas declarar un componente dentro de un contexto equivocado, por ejemplo, al declarar un componente  window  como hijo de un componente  listbox .

Un componente anidado

Un listbox es un componente anidado, el cual soporta dos tipos de componentes hijos, listhead (aka: columna de la tabla), and listitem (aka: fila de la tabla). Con la declaración del  listbox, asiganamos el atributo id a 「box」, ahora podemos usar este atributo para referenciar el listbox.

<window id="win" title="To do list" width="640px" border="normal">
	<listbox id="box" multiple="true" rows="5">
		<listhead>
		</listhead>		
		<listitem>	
		</listitem>
	</listbox>
</window>

Aún no hemos terminado. Vamos a declarar tres componentes listheader dentro de los tags de listhead. Necesitamos tres columnas -- 「Item」, 「Priority」, and 「Date」 -- dentro de la tabla, como se indica:

<window id="win" title="To do list" width="640px" border="normal">
	<listbox id="box" multiple="true" rows="5">
		<listhead>
			<listheader label="Item" />
			<listheader label="Priority" width="80px" />
			<listheader label="Date" width="170px" />
		</listhead>		
		<listitem>
		</listitem>
	</listbox>
</window>


Tenemos tres columnas en nuestra tabla, cada fila de la tabla también requerirá tres campos. Declaramos tres componentes listcell dentro de los tags del componente listitem.


<window id="win" title="To do list" width="640px" border="normal">
	<listbox id="box" multiple="true" rows="5">
		<listhead>
			<listheader label="Item" />
			<listheader label="Priority" width="80px" />
			<listheader label="Date" width="170px" />
		</listhead>		
		<listitem>			
			<listcell />
			<listcell />
			<listcell />
		</listitem>
	</listbox>
</window>

La estructura anidada del componente  listbox  quedaría así,

listbox 
+-- listhead
|    |
|    +-- listheader
|
+-- listitem
      |
     +-- listcell

Componentes para introducir información

En adición a mostrar estes eventos en el  listbox, necesitamos introducir información relativa al evento, incluyendo el evento name (campo texto), el evento priority (campo numérico) y el evento date (campo fecha). Para lograr esto, declaramos un we declare un textbox, un intbox y un datebox dentro de los tags del compoente  window  de la siguiente forma:

<window id="win" title="To do list" width="640px" border="normal">
	<listbox id="box" multiple="true" rows="5">
		<listhead>
			<listheader label="Item" />
			<listheader label="Priority" width="80px" />
			<listheader label="Date" width="170px" />
		</listhead>		
		<listitem>			
			<listcell />
			<listcell />
			<listcell />
		</listitem>
	</listbox>
	Item: <textbox id="name" cols="25" />
	Priority: <intbox id="priority" cols="1" />
	Date: <datebox id="date" cols="8" />
	<button id="add" label="Add" />
	<button id="update" label="Update" />
	<button id="delete" label="Delete" />
</window>

Componentes Layout

Para distinguir los componentes de entrada de datos (input) de los componentes listbox de abajo, declaramos un groupbox para agrupar los componentes. Esto dibujará un borde alrededor de los componentes que estén contenidos dentro del groupbox, en este caso, los componentes de entrada de datos (input).

<window id="win" title="To do list" width="640px" border="normal">
	<listbox id="box" multiple="true" rows="5">
		<listhead>
			<listheader label="Item" />
			<listheader label="Priority" width="80px" />
			<listheader label="Date" width="170px" />
		</listhead>		
		<listitem>			
			<listcell />
			<listcell />
			<listcell />
		</listitem>
	</listbox>
	<groupbox>
		<caption label="Event" />
		Item: <textbox id="name" cols="25" />
		Priority: <intbox id="priority" cols="1" />
		Date: <datebox id="date" cols="8" />
		<button id="add" label="Add" />
		<button id="update" label="Update" />
		<button id="delete" label="Delete" />
	</groupbox>	
</window>

Adicionalmente a los componentes  groupbox  declaramos un componente  caption  para mostrar una etiqueta 「Event」 a lo largo de la caja que agrupa a los componentes. El componente caption trabaja de forma similar al legendario elemento en HTML.

Controlador

Nuestros requisitos incluyen mostrar, añadir, editar y borrar sucesos/eventos. En los siguientes párrafos, implementaremos las interacciones entre nuestra aplicación web y la base de datos.

Definiendo un Controlador

El primer paso es definir un EventController el cual herede de org.zkoss.zk.ui.util.GenericForwardComposer.

Implementando org.zkoss.zk.ui.util.GenericForwardComposer

Crea un EventController el cual heredará de org.zkoss.zk.ui.util.GenericForwardComposer permitiéndote un fácil acceso a la vista y definir un CRUD mediante los métodos Java definidos.

// org.zkforge.todo.event.EventController.java

public class EventController extends GenericForwardComposer {
    private static final long serialVersionUID = -9145887024839938515L;
    private EventDAO eventDao = new EventDAO();

    // Note: Something is omitted at here. You can view detail about this class on source code.

    public List<TodoEvent> getAllEvents() {
        return eventDao.findAll();
    }

    public void onClick$add() {
    }

    public void onClick$update() {
    }

    public void onClick$delete() {
    }
}

Asociando el Controlador con la Vista

Para implmentar la interacción entre la Vista y el Controlador asignamos el atributo apply al componente window en la ruta de nuestro EventController.

<window id="win" title="To do list" width="640px" border="normal"
 apply="org.zkforge.todo.event.EventController">

......

Visualizando datos en una Vista

Para visualizar los datos recuperados de la base de datos en nuestra Vista solo requerimos tres pasos:


Activando el mecanismo de DataBinding

Para usar el mecanismoData Binding, deberemos activar el Data Binding Manager (org.zkoss.zkplus.databind.AnnotateDataBinderInit) en la parte superior de la página.

<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit"?>

<window id="win" title="To do list" width="640px" border="normal"
 apply="org.zkforge.todo.event.EventController">
....

Asociando los datos con la vista

El paso siguiente es recuperar los datos de la base de datos mediante el EventController usando la expresión (win$composer.allEvents) para invocar EventController.getAllEvents(). El método EventController.getAllEvents() devuelve una lista que contiene todos los eventos almacenados en la base de datos que pueden ser asociados al atributo model del Listbox.


<window id="win" title="To do list" width="640px" border="normal"
 apply="org.zkforge.todo.event.EventController">
	<listbox id="box" multiple="true" rows="5" model="@{win$composer.allEvents}">
....

Puedes seguir los siguientes pasos para definir una plantilla de Interfaz de Usuario para renderizar los datos dentro de la vista.

Definiendo una plantilla

Es posible definir una plantilla de interfaz de usuario para renderizar DataBinding dentro de los correspondientes componentes de interfaz de usuario. Esto se logra gracias a la utilización de los atributos que ofrece el componente "listitem" definiendo una varible para representar cada instancia a reflejar.

<window id="win" title="To do list" width="640px" border="normal"
 apply="org.zkforge.todo.event.EventController">
	<listbox id="box" multiple="true" rows="5"
     model="@{win$composer.allEvents, load-after='add.onClick, delete.onClick, update.onClick'}" 
     selectedItem="@{win$composer.current}">
		<listhead>
			<listheader label="Item" sort="auto(name)" />
			<listheader label="Priority" width="80px" sort="auto(priority)" />
			<listheader label="Date" width="170px" sort="auto(date)" />
		</listhead>		
		<listitem self="@{each='event'}" value="@{event}">			
			<listcell label="@{event.name}" />
			<listcell label="@{event.priority}" />
			<listcell label="@{event.date}" />
		</listitem>
	</listbox>

Para más información, por favor dirígete a Associate UI Components with a Collection.

Sincronización de vistas

Una vez el usuario selecciona un ToDoEvent en el listbox, Necesitamos mostrarlo en el componente groupbox también. Sería mucho mejor si este tedioso trabajo fuera realizado de forma automáticamente. Data Binding es la respuesta! Simplemente asocia los datos con todo lo relacionado con los componentes de UI. El DataBinding se sincronizará entonces con todos los componentes de Interfaz de Usuario una vez la propiedad ha sido modificada.

Definir una instancia "ToDoEvent" a un Controlador

Define una instnacia ToDoEvent' en EventController, y define métodos getter y setter para que puedan ser accesibles desde la vista.

// org.zkforge.todo.event.EventController.java

public class EventController extends GenericForwardComposer {
    private TodoEvent current = new TodoEvent();
    // Omitted...
    public TodoEvent getCurrent() {
        return current;
    }

    public void setCurrent(TodoEvent current) {
        this.current = current;
    }

Asociando múltiples componentes UI con la instancia EventController

Primero, asocia la instancia EventController con la propiedad selectedItem del listbox. Después, asocia las propiedades del ToDoEvent con el correspondiente componentes UI, incluyendo textbox, intbox, y datebox. Una vez el usuario selecciona un item en un listbox, la instnacia se actualizará en relación a los componentes UI.

	<listbox id="box" multiple="true" rows="5"
      model="@{win$composer.allEvents, load-after='add.onClick, delete.onClick, update.onClick'}" 
      selectedItem="@{win$composer.current}">
	<!-- Omitted -->
	<groupbox>
		<caption label="Event" />
		Item: <textbox id="name" cols="25" value="@{win$composer.current.name}" />
		Priority: <intbox id="priority" cols="1" value="@{win$composer.current.priority}" />
		Date: <datebox id="date" cols="8" value="@{win$composer.current.date}" />

Sincronizando la vista con la base de datos

Además de mostrar los datos de la base de datos en la vista, nos gustaría implementar eventos para añadir, actualizar y eliminar. Esta funcionalidad requiere de tres pasos, monitorizar la actividad del usuario, interactuando con los controladores para actualizar la base de datos y actualizar la vista.

Registrar el evento Listener en el Controlador

Para monitorizar la actividad del usuario, simplente registrarmos un evento listener onClick' en los siguientes tres botones add, update and delete. Cuando cliqueamos en estos botones que se corresponden a los métodos definidos en EventController estos serán invocados. Estos métodos son definidos así:

public class EventController extends GenericForwardComposer {
    private EventDAO eventDao = new EventDAO();
    // Omitted...
    public void onClick$add() {
        if (current != null) {
            current.setId(UUID.randomUUID().toString());
            
            if (validate(current)) {
                // insert into database
                eventDao.insert(current);
            }
        }
    }

    public void onClick$update() {
        if (current != null && validate(current)) {
            // update database
            eventDao.update(current);
        }
    }

    public void onClick$delete() {
        if (current != null && validate(current)) {
            eventDao.delete(current);
        }
    }
}
		<button id="add" label="Add" />
		<button id="update" label="Update" />
		<button id="delete" label="Delete" />

Actualizar la vista usando Databinding

Después de interactuar con la base de datos, el último paso es actualizar la vista. Simplemente notificar al Databinding para que actualice el modelo por ti, cuando el usuario cliquée en cualquier botón. Intenta registrar un atributo load-after en el atributo model del listbox, y el Databinding actualizará la vista automáticamente si el evento especificado es capturado.

<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit"?>

<window id="win" title="To do list" width="640px" border="normal"
 apply="org.zkforge.todo.event.EventController">
	<listbox id="box" multiple="true" rows="5"
     model="@{win$composer.allEvents, load-after='add.onClick, delete.onClick, update.onClick'}" 
     selectedItem="@{win$composer.current}">
	<!-- Omitted... -->
		<button id="add" label="Add" />
		<button id="update" label="Update" />
		<button id="delete" label="Delete" />
	</groupbox>	
</window>

Last Update : 2012/02/10