Conserver les bonnes données après validation

A la suppression d'élément sur une form collection

a marqué ce sujet comme résolu.

Hello tout le monde,

J'essaie de valider la suppression d'éléments sur un formulaire de type collection (dynamique). Pour la validation, pas trop de problème (je donne le validator à titre indicatif). Par contre une fois le form réaffiché, il est affiché sans les données supprimées ! (du coup sa re-validation est compromise)

Avez vous une idée de comment régler ce problème ? Je donne des fichiers qui permettront peut être de mieux comprendre le problème.

  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
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
<?php

class AppointmentController extends Controller
{

    public function editAppointment(Request $request, Appointment $appointment)
    {
        // Here
        // count($appointment->getSlot()) === 3

        $form = $this->createForm('appointment', $appointment, [
            'questionnaire' => $questionnaire
        ]);
        $form->handleRequest($request);

        if ($form->isValid()) {
            // Persisting
        }

        // Here on failing validation, there is
        // count($appointment->getSlot()) === 2
        // Because we removed one slot from "dynamically" in the form, but the user can't do that,
        // so we need to reset the slots but it's not possible because form data is locked after "submit".
        return $this->render('App:Appointment:edit.html.twig', ['form' => $form->createView()]);
    }
}

class AppointmentType extends AbstractTYpe
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('slots', 'collection', [
                'type' => new SlotType(),
                'allow_add' => true,
                'prototype' => true,
                'allow_delete' => true,
                'error_bubbling' => false,
                'by_reference' => false,
                'constraints' => [
                    new WrongSlotRemoval($builder->getData()->getSlots())
                ]
            ])
        ;
    }
}

class WrongSlotRemoval extends Constraint
{
    public $message = 'Impossible to delete slog.';

    /**
     * @var null|\App\Entity\AppointmentSlot[]
     */
    private $slots;

    /**
     * @param \App\Entity\AppointmentSlot[]|null $slots
     */
    public function __construct($slots = null)
    {
        // Clone the collection because it can be modified by reference
        // in order to add or delete items.
        if ($slots !== null) {
            $this->slots = clone $slots;
        }
    }

    /**
     * @return \App\Entity\AppointmentSlot[]
     */
    public function getSlots()
    {
        return $this->slots;
    }

    /**
     * @param \App\Entity\AppointmentSlot[] $slots
     * @return self
     */
    public function setSlots($slots)
    {
        $this->slots = $slots;

        return $this;
    }
}

class WrongSlotRemovalValidator extends ConstraintValidator
{
    /**
     * @param \App\Entity\AppointmentSlot[] $object
     * @param WrongSlotRemoval $constraint
     */
    public function validate($object, Constraint $constraint)
    {
        foreach($constraint->getSlots() as $slot) {
            if (!$object->contains($slot) && !$slot->isDeletable()) {

                $this->context
                    ->buildViolation($constraint->message)
                    ->addViolation()
                ;

                return;
            }
        }
    }
}

Merci d'avance !

[edit] Voici un screen du problème:

+1 -1

Salut !

Excuse-moi, je suis probablement fatigué, mais je n'arrive pas à saisir. Tu dis que le formulaire, en se réaffichant, n'a plus les informations du slot supprimé. Moi, si je m'arrête là, je comprends que le formulaire a été soumis, la suppression validée et effectuée, et qu'on réaffiche le formulaire avec les informations disponibles, qui pour moi ne comprennent évidemment plus les informations qu'on vient justement de supprimer… mais tu souhaiterais les avoir quand-même ?

+0 -0

Hello,

La suppression n'a pas été validée (l'erreur de validation en atteste). Mais quand tu mets un mauvais pseudo dans un input text qui ne passe pas la validation par exemple, tu vas avoir la nouvelle donnée malgré tout dans ton form. Et bah c'est la même chose, sauf que là c'est problématique.

Et pour information j'ai été jusqu'au bout de la démarche, et c'est une limitation de Symfony. Donc il y a une PR à faire, et pas vraiment de solution mis à part créer un nouveau form sur lequel on ajoute les erreurs de l'ancien form une par une…

(et il faudra qu'on m'explique ce que j'ai fait de mal pour prendre un "-1")

+0 -0

D'accord, je saisis. En fait, le problème c'est que la soumission du formulaire reprend les données qui ont été envoyées, et dans le cas où tu fais de la validation pour la suppression des éléments d'une collection, c'est problématique, parce que les données soumises ne contiennent plus ce qui a généré l'erreur…

Est-ce qu'il n'y a pas moyen, d'une manière ou d'une autre, de savoir si le champ de collection a une erreur (et même si c'est l'erreur de validation de suppression), et de ne recharger que la collection depuis la base de données, afin d'avoir l'erreur et les données ?

(et il faudra qu'on m'explique ce que j'ai fait de mal pour prendre un "-1")

Nek

Je te garantis que ce n'est pas moi, pour ma part le fait de ne pas comprendre ne justifierait en aucun cas ce genre de comportement à mon avis débile.
Je penche pour l’œuvre d'un troll qui est bien content de pouvoir juste cliquer sur -1 parce qu'il peut le faire et ne rien dire dans le sujet.

+0 -0

T'as bien compris le problème. Par contre il n'y a pas de solution car le form est lock après submit des données. Du coup impossible de le modifier. C'est une issue de Symfony, pour l'instant pas de solution. https://github.com/symfony/symfony/issues/5480

La seule solution c'est ce dont j'ai déjà parlé :

créer un nouveau form sur lequel on ajoute les erreurs de l'ancien form

Avec une mise en session des erreurs et une redirection c'est peut être un peu plus esthétique, mais toujours bof.

Est-ce qu'implémenter un comportement "softdeletable", où tu ne fais que masquer les éléments à supprimer en leur ajoutant d'une manière ou d'une autre un tag, et tu les supprimes réellement selon le tag, pourrait être imaginable ?

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte