Développer une application avec le framework Play !


précédentsommairesuivant

X. Création d'une zone de saisie personnalisée

Dans le chapitre précédent, nous avons créé une interface d'administration pour notre application yabe, et préparé la section "Mes billets" (My posts). Cette page va afficher, pour un auteur donné, l'ensemble de ses billets, avec la possibilité de les modifier ou d'en écrire de nouveaux.

Nous pourrions partir du module CRUD pour créer cette page, mais nous décidons ici de partir de zéro, car nous avons besoin de la rendre très personnalisable.

X-A. Lister les billets de l'auteur

Notre première étape consiste à récupérer la liste des billets écrits par l'utilisateur actuellement connecté. Améliorons donc notre action Admin.index :

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

Complétons également le template /yabe/app/views/Admin/index.html :

 
Sélectionnez
#{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>

Notre premier écran est désormais disponible :

Image non disponible

X-B. La page d'écriture d'un billet

Nous allons construire un formulaire destiné à l'écriture d'un nouveau billet. Généralement, pour un formulaire donné, nous avons deux actions : l'une pour afficher le formulaire, l'autre pour gérer sa soumission. Créons ainsi les actions Admin.form et Admin.save qui vont gérer ces deux actions.

Tout d'abord modifions le fichier /yabe/conf/routes :

 
Sélectionnez
GET     /admin/new                          Admin.form
POST    /admin/new                          Admin.save

Dans la classe Admin.java, ajoutons les méthodes form() et save() :

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

Bien sûr, créons le template /yabe/app/views/Admin/form.html :

 
Sélectionnez
#{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}

Editons le fichier /yabe/app/views/Admin/index.html pour lier le bouton "Ecrire un nouveau billet" (Write a new post) à ce nouveau formulaire :

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

Vérifions le résultat :

Image non disponible

Nous avons terminé la déclaration de l'action Admin.save pour gérer correctement la soumission du formulaire. Celle-ci va créer un nouvel objet Post, convertir la liste des tags en une liste d'objets Tag, valider les champs, puis finalement sauvegarder le tout. En cas de problème, cette action réaffichera le formulaire ainsi que les messages d'erreur.

 
Sélectionnez
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();
}

Ici, nous utilisons render("@form") comme un raccourci de render("Admin/form.html"). Cette forme d'écriture indique juste à Play d'utiliser le template par défaut pour cette action.

Nous pouvons tester...

X-C. Réutilisation pour l'édition d'un billet

Nous avons réalisé un formulaire HTML ainsi que l'action Java permettant d'écrire un nouveau billet. Nous voulons maintenant ajouter la fonctionnalité d'édition d'un billet. Réutiliser le code existant s'avère relativement facile et ne demandera que quelques modifications.

Tout d'abord, modifions l'action Admin.form pour récupérer un billet existant :

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

Comme vous pouvez le voir, nous avons rendu le paramètre id optionnel. De cette façon, nous n'afficherons le Post que si ce paramètre est renseigné. Nous pouvons lier la liste des billets de l'écran principal à la page d'édition. Editons le template /yabe/app/views/Admin/index.html :

 
Sélectionnez
#{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>

Cela parait facile, mais nous avons toutefois un petit problème ici. Si nous regardons l'URL générée par le Router pour ces liens, nous voyons quelque chose comme ceci :

 
Sélectionnez
/admin/new?id=3

Cela fonctionne, mais ce n'est pas très joli ! Nous définissons donc un nouveau type de route lorsque l'attribut id est soumis :

 
Sélectionnez
GET     /admin/myPosts/{id}                 Admin.form
GET     /admin/new                          Admin.form

Constatez que nous définissons cette route avant l'ancienne, de telle façon à ce qu'elle ait une priorité plus forte. Cela signifie que si une id est soumise, Play privilégiera cette première route. Dans le cas contraire, ce sera la seconde route qui sera utilisée.

Rafraichissons la page de "Mes billets", et nous devrions voir une URL plus propre maintenant.

Il nous faut modifier le template /yabe/app/views/Admin/form.html :

 
Sélectionnez
#{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}

Nous avons ici mis à jour l'action de destination du formulaire afin d'ajouter l'identifiant du billet comme premier paramètre, si celui-ci existe. Ainsi, si le billet a effectivement un identifiant (ce qui signifie qu'il s'agit d'un billet déjà existant), alors il sera envoyé à l'action Admin.save.

Nous pouvons désormais modifier un petit peu la méthode save() pour gérer aussi bien la création que l'édition d'un billet :

 
Sélectionnez
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();
}

Pour améliorer l'URL nous pouvons utiliser la même astuce que précédemment, en ajoutant une route qui sera privilégiée si un id est fourni :

 
Sélectionnez
POST    /admin/myPosts/{id}                  Admin.save
POST    /admin/new                          Admin.save

Voilà qui est terminé ! Nous utilisons désormais la même action pour créer de nouveaux billets, et éditer les existants. Notre travail sur l'interface d'administration est achevé !


précédentsommairesuivant

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

Ce document est issu de http://www.developpez.com et reste la propriété exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise à l'obtention préalable de l'autorisation de l'auteur.