¡La versión 2.0 de Play ya está lista! Ayúdanos a traducir la documentación de la útlima versión y sigue nuestro progreso.

Manuales, tutoriales & referencias

Consulte

Contenidos

Elija la versión

Buscar

Busque con google

Libros

Creando un área para editores personalizada

En la parte anterior creamos un área de administración para yabe y preparamos la sección ‘My Posts’. Esta sección mostrará a cada autor una lista de sus propias publicaciones (posts), y tendrá la opción de editarlas o crear nuevas entradas.

Podríamos fácilmente reutilizar el módulo CRUD como base para esta página, pero en este caso la crearemos desde cero; ya que el área de editores necesita muchas características personalizadas.

Comencemos con la lista de posts del usuario

Sólo necesitamos consultar y mostrar los posts escritos por el usuario que ha iniciado la sesión. Esto es muy fácil. Empecemos por mejorar la acción Admin.index:

public static void index() {
    String user = Security.connected();
    List<Post> posts = Post.find("author.email", user).fetch();
    render(posts);
}

Y modifique el archivo yabe/app/views/Admin/index.html:

#{extends 'admin.html' /}
 
<h3>Welcome ${user}, <span>you have written ${posts.size() ?: 'no'} 
${posts.pluralize('post', 'posts')} so far</span></h3>
 
#{list items:posts, as:'post'}
    <p class="post ${post_parity}">
        <a href="#">${post.title}</a>
    </p>
#{/list}
 
<p id="newPost" >
    <a href="#"><span>+</span> write a new post</a>
</p>

La primera página está lista:

La página ‘write a new post’

Ahora crearemos un formulario para escribir nuevos posts. Básicamente cuando trabajamos con un formulario tenemos que ejecutar dos acciones: una para mostrar el formulario y la otra para capturar los datos introducidos en el mismo. Vamos a crear dos nuevas acciones llamadas Admin.form y Admin.save que se encargaran de realizar estas tareas.

Primero, agruegue las rutas al archivo yabe/conf/routes:

GET     /admin/new                          Admin.form
POST    /admin/new                          Admin.save

Luego agregue las acciones form() y save() al controlador Admin.java:

public static void form() {
    render();
}
 
public static void save() {
    // Not implemented yet
}

Ahora tiene que crear la plantilla yabe/app/views/Admin/form.html:

#{extends 'admin.html' /}
 
<h3>Write, <span>a new post</span></h3>
 
#{form @save()}
 
    #{ifErrors}
        <p class="error">
            Please correct these errors.
        </p>
    #{/ifErrors}
     
    <p>
        #{field 'title'}
        <label>Post title:</label>
        <input type="text" name="${field.name}" 
            value="${post?.title}" class="${field.errorClass}" />
        #{/field}
    </p>
 
    <p>
        #{field 'content'}
        <label>Write here:</label>
        <textarea name="${field.name}" 
            class="${field.errorClass}">${post?.content}</textarea>
        #{/field}
    </p>
 
    <p>
        #{field 'tags'}
        <label>Enter some tags:</label>
        <input type="text" size="50" 
            name="${field.name}" value="${post?.tags?.join(' ')}" />
        #{/field}
    </p>
    
    <p>
        <input type="submit" value="Publish this post to the blog" />
    </p>
    
#{/form}

Finalmente, modifique la plantilla yabe/app/views/Admin/index.html para enlazar el botón Write a new post y apunte a este formulario:

...
<p id="newPost" >
    <a href="@{form()}"><span>+</span> write a new post</a>
</p>
...

Ya puede revisar el resultado:

Ahora tenemos que completar la acción Admin.save para capturar correctamente los datos del formulario. Esta acción creará un nuevo objeto Post, convertirá la lista de etiquetas en una colección de objetos Tag, validará todos los campos y los guardará. Si hay algún problema entonces volverá a mostrar el formulario con los correspondientes mensajes de error.

public static void save(String title, String content, String tags) {
    // Create post
    User author = User.find("byEmail", Security.connected()).first();
    Post post = new Post(author, title, content);
    // Set tags list
    for(String tag : tags.split("\\s+")) {
        if(tag.trim().length() > 0) {
            post.tags.add(Tag.findOrCreateByName(tag));
        }
    }
    // Validate
    validation.valid(post);
    if(validation.hasErrors()) {
        render("@form", post);
    }
    // Save
    post.save();
    index();
}

Aquí usamos la instrucción render("@form") que viene a ser una versión simplificada de la instrucción render("Admin/form.html"). Esta instrucción simplemente le dice a Play que utilice la plantilla por defecto de la acción ‘form’.

¡Hagan la prueba!

Reutilizando todo esto para editar Posts

Hemos construido el formulario HTML y la acción Java capaces de crear un nuevo Post en el blog, sin embargo, aún nos falta permitir la edición de los posts existentes. Podemos, de manera muy sencilla, reutilizar exactamente el mismo código anterior, sólo que haciéndole unas pequeñas modificaciones.

Primero necesitamos que Admin.form pueda además obtener los datos de un Post existente:

public static void form(Long id) {
    if(id != null) {
        Post post = Post.findById(id);
        render(post);
    }
    render();
}

Como puede observar, lo colocamos de manera opcional; de esta forma la misma acción consultará los datos de un post sólo si se proporciona un valor a través del parámetro id. Ahora puede enlazar los posts de la lista en la página principal para que apunten al formulario de edición. Modifique la plantilla yabe/app/views/Admin/index.html:

#{extends 'admin.html' /}
 
<h3>Welcome ${user}, <span>you have written ${posts.size() ?: 'no'} ${posts.pluralize('post', 'posts')} so far</span></h3>
 
#{list items:posts, as:'post'}
    <p class="post ${post_parity}">
        <a href="@{Admin.form(post.id)}">${post.title}</a>
    </p>
#{/list}
 
<p id="newPost" >
    <a href="@{form()}"><span>+</span> write a new post</a>
</p>

Bien, muy fácil pero tenemos un problema. Si se fija en la URL generada por el Router para estos enlaces, debería ver algo como esto:

/admin/new?id=3

Funciona, pero no es muy bonito que digamos. Por lo que definiremos otra ruta que usará un patrón URL diferente cuando se utilice el parámetro id:

GET     /admin/myPosts/{id}                 Admin.form
GET     /admin/new                          Admin.form

Cabe destacar que colocamos la definicion de esta nueva ruta por encima de la vieja, con el fin de que tenga mayor prioridad. Esto significa que si se utiliza el parámetro id, Play utilizará el patrón URL nuevo. En caso contrario, utilizará el viejo.

Actualice la página My posts y debería ver los nuevos URL en estos enlaces.

También necesitamos modificar la plantilla yabe/app/views/Admin/form.html:

#{extends 'admin.html' /}
 
#{ifnot post?.id}
    <h3>Write, <span>a new post</span></h3>
#{/ifnot}
#{else}
    <h3>Edit, <span>this post</span></h3>
#{/else}
 
#{form @save(post?.id)}
 
    #{ifErrors}
        <p class="error">
            Please correct these errors.
        </p>
    #{/ifErrors}
     
    <p>
        #{field 'title'}
        <label>Post title:</label>
        <input type="text" name="${field.name}" 
            value="${post?.title}" class="${field.errorClass}" />
        #{/field}
    </p>
 
    <p>
        #{field 'content'}
        <label>Write here:</label>
        <textarea name="${field.name}" 
            class="${field.errorClass}">${post?.content}</textarea>
        #{/field}
    </p>
 
    <p>
        #{field 'tags'}
        <label>Enter some tags:</label>
        <input type="text" size="50" 
            name="${field.name}" value="${post?.tags?.join(' ')}" />
        #{/field}
    </p>
    
    <p>
        <input type="submit" value="Publish this post to the blog" />
    </p>
    
#{/form}

Como puede ver, hemos actualizado la acción de destino del formulario para que agregue el ID del post como primer parámetro de la acción, en caso de que éste exista. Por lo tanto cuando el post tenga un campo id con valor asignado (es decir que el post ya existe en el sistema), el formulario lo enviará a la acción Admin.save.

Ahora podemos adaptar el método save() para que pueda manejar ambos casos de creación y edición:

public static void save(Long id, String title, String content, String tags) {
    Post post;
    if(id == null) {
        // Create post
        User author = User.find("byEmail", Security.connected()).first();
        post = new Post(author, title, content);
    } else {
        // Retrieve post
        post = Post.findById(id);
        // Edit
        post.title = title;
        post.content = content;
        post.tags.clear();
    }
    // Set tags list
    for(String tag : tags.split("\\s+")) {
        if(tag.trim().length() > 0) {
            post.tags.add(Tag.findOrCreateByName(tag));
        }
    }
    // Validate
    validation.valid(post);
    if(validation.hasErrors()) {
        render("@form", post);
    }
    // Save
    post.save();
    index();
}

Y para obtener una mejor URL usemos el mismo truco de antes, agregando una nueva ruta preferida para los casos en que se utiliza el parámetro id:

POST    /admin/myPosts/{id}                 Admin.save
POST    /admin/new                          Admin.save

¡Listo! Ahora estamos usando la misma acción para realizar dos tareas diferentes: crear posts nuevos y editar los existentes, y con esto ¡terminamos el area de administración!

Continúa con: Completando las pruebas de la aplicación.