par , 23/09/2016 à 13h44 (4861 Affichages)
Bonjour,
Ce billet et une continuation de l’ancien billet manipuler une dataTable js
http://www.developpez.net/forums/blo...table-symfony2
A travers ce billet vous allez pouvoir améliorer l'exemple précédent en ajoutant un utilisateur via une popup.
Intro
J’ai pensé au début à créé un nouveau template pour l’ajout, mais ceci va nous obliger de quitter la page et perdre les fonctionnalités de refresh de dataTable, pour cela on va proposer à l’utilisateur un formulaire dans une popup qui lui permettra d’ajouter une entrée dans la base sans qu’il quitte la page des listes d’utilisateurs et pouvoir la rafraichir pour voir la nouvelle entrée, pour l’exemple je vais utiliser la popup de bootstrap.
Donc pour mettre le tout en place, j’ai effectué quelques modifications
Importent: j'ai mis a jour la version du framework vers v3.
la création d’un nouveau bundle nommé AppBundle et déplacement des vues dedans (à partir du dossier Resources sous /app)
L’ajout plusieurs lib javascript:
Bootstrap: servira à améliorer l’ergonomie et la mise en page du site, et pour la popup javascript
jquery.form.js: pour simplifier l’envoi des formulaires en ajax
J’ai aussi utiliser le layout bootstrap suivant pour améliorer l’affichage
http://getbootstrap.com/examples/dashboard/
1/ Ajouter le formType
Pour ajouter une classe de formulaire, lancer tout simplement la commande
php bin/console generate:doctrine:form AppBundle:User
Un fichier sera créé sous AppBundle/Form, modifier le pour avoir le contenu suivant
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
|
<?php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class UserType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
;
}
/**
* @param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\User'
));
}
} |
2/ Ajouter l’action associé qui à travers, on pourra instancier le FormType et et le passer au rendu:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
use Symfony\Component\Form\Extension\Core\Type\TextType;
use AppBundle\Entity\User;
use AppBundle\Form\UserType;
.
.
/**
* @Route("/user/new", name="user_new")
*/
public function newAction(Request $request)
{
$user = new User();
$form = $this->createForm(UserType::class, $user);
return $this->render('AppBundle:user:new.html.twig', array(
'form' => $form->createView(),
));
} |
Créer la vue pour afficher le formulaire
La vue contiendra des éléments html relatifs à la modal bootstrap ainsi que la fonction javascript pour envoyer le formulaire en ajax
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
|
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title">Ajouter un utilisateur</h4>
</div>
<form method="post" action="{{path('user_create')}}" class="user-create-form">
<div class="modal-body">
{{form_widget(form)}}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">fermer</button>
<button type="submit" class="btn btn-primary">Enregistrer</button>
</div>
</form>
<script>
$('.user-create-form').submit(function(e) {
e.preventDefault();
$(this).ajaxSubmit({
dataType: 'json',
success: function(result){
if (result.status == 'ok'){
userTable.ajax.reload();
$('#myModal').modal('hide');
}
}
});
return false;
});
</script> |
La mise en forme avec le layout
Aussi le layout principale est à changer pour inclure le html de base de la popup, le nouveau design et les différents scripts et styles de librairies tiers
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
|
<html>
<head>
{%block css%}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdn.datatables.net/1.10.6/css/jquery.dataTables.min.css" />
<link rel="stylesheet" href="https://cdn.datatables.net/1.10.12/css/dataTables.bootstrap.min.css" />
<style type="text/css">
</style>
{% endblock %}
</head>
</html>
<body cz-shortcut-listen="true">
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">dataTable exemple</a>
</div>
{% block actions %}
{% endblock %}
</div>
</nav>
<div class="container-fluid">
<div class="row">
<div class="col-sm-12 main">
<br />
{% block body %}
{% endblock %}
</div>
</div>
</div>
</div>
<!-- /.modal source code -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content"></div>
</div>
</div>
</body>
{% block javascript %}
<script src="https://code.jquery.com/jquery-1.11.2.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<script src="https://cdn.datatables.net/1.10.6/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/1.10.12/js/dataTables.bootstrap.min.js"></script>
<script type="text/javascript" src="http://malsup.github.io/min/jquery.form.min.js"></script>
{% endblock %} |
la page liste des utilisateurs
Reste aussi le code de la page liste des utilisateurs, j’ai un peut changer son code js pour pouvoir l’adapter à la nouvelle fonctionnalité d’ajout.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
|
{% extends "AppBundle::base.html.twig" %}
{% block actions %}
<ul class="nav navbar-nav navbar-right">
<li><a class="btn btn-link user-add-btn" href="{{ path('user_new') }}"><i class="glyphicon glyphicon-plus"></i> Ajouter</a></li>
</ul>
{% endblock %}
{% block body %}
<h1 class="page-header">Liste des utilisateurs</h1>
<table id="user-list" class="table table-striped"></table>
{% endblock %}
{% block javascript %}
{{ parent() }}
<script>
var userTable;
$(function() {
//C'est le bouton qui affiche la popup, et charge aussi le formulaire dans cette dernière.
$('.user-add-btn').click(function(e) {
$.get(e.currentTarget.href, function(html){
$('#myModal .modal-content').html(html);
$('#myModal').modal('show');
});
e.preventDefault();
});
userTable = $('#user-list').DataTable({
"processing": true,
"serverSide": true,
"ajax": "{{ path('user_paginate') }}",
"sAjaxDataProp": "data",
"pageLength": 10,
"columns":[
{"data": "id"},
{"data": "name"},
{"data": "created_at"}
]
});
});
</script>
{% endblock %} |
Vous pourriez actuellement afficher le contenu du formulaire dane la popup en cliquant sur Ajouter
Pour pouvoir insérer le nouvelle entrée dans la base il nous fera une nouvelle action createAction
Le rôle de cette action est de prendre les données envoye en POST.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
/**
* @Route("/user/create", name="user_create")
*/
public function createAction(Request $request)
{
$user = new User();
$form = $this->createForm(UserType::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
dump($form->getData());
die;
}
} |
Si à ce stade là vous rencontrez l’erreur suivante
C’est parce qu'il ne trouve pas une méthode capable de binder la valeur du champs name du formulaire avec l’attribut name de la classe.
Il suffit donc d’ajouter les setters des attributs, du coup voici le code de la class User
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
|
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* User
*
* @ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
* @ORM\Table(name="users")
*/
class User
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @var string
*
* @ORM\Column(type="string")
*/
private $name;
/**
* @var string
*
* @ORM\Column(type="datetime")
*/
private $createdAt;
public function __construct()
{
$this->createdAt = new \dateTime('now');
}
public function getId()
{
return $this->id;
}
public function getName()
{
return $this->name;
}
public function getCreatedAt()
{
return $this->createdAt;
}
public function setName($name)
{
$this->name = $name;
return $this;
}
public function setCreatedAt($createdAt)
{
$this->createdAt = $createdAt;
return $this;
}
} |
Reste maintenant l’insertion dans la base de données, pour cela ajoutant deux lignes, qui a la suite font appel au service doctrine.manager et permettent de persister l’objet et l'insérer dans la base.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
/**
* @Route("/user/create", name="user_create")
*/
public function createAction(Request $request)
{
$user = new User();
$form = $this->createForm(UserType::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($user);
$em->flush();
return new JsonResponse(['status' => 'ok']);
} else {
return new JsonResponse(['status' => 'ko']);
}
} |
@todo
Dans le prochain tuto
- Supprimer un utilisateur
- Modifier un utilisateur
- Afficher les détails
- Améliorer le filtre avec un critère supplémentaire: la date de création