Bonjour,

Je dois faire un système avec des LiveComponent ou en cliquant sur un bouton, cela ouvre un modal, affiche et gère un formulaire depuis un FormType. Si la validation est bonne, affiche une notification sinon on reste sur le modal avec les champs erronés mis en valeur.

je suis arrivé à afficher une modal en lui passant le path de l'action à effectuer.

Maintenant je cherche à afficher et gérer le formulaire.

Si quelqu'un a déjà eu à faire cela je suis preneur de tips.

Merci

9 réponses


Salut,
Sans code c'est compliqué de t'aider.
1- Tu as un bouton qui te permet d'afficher un modal.
2- ton formType est dans ta modal. Le buton validé sera le submit du formulaire.

C'est tout, il n'y a pas de tips particulier.

Coucou

le hic est que le form ne peut être "en dur" dans le modal sinon je n'aurais pas besoin d'un LiveComponent :) En fait le form doit être intégré au modal lors avant l'affichage de la modal, ce qui me permet de n'avoir qu'un seul modal dans la page, malgré le fait que l'on puisse avoir autant de formulaires que la page nécessite.

Tu as raison, sans code c'est pas top, donc voilà ) peu près ce que j'ai

J'ai un modal-controller.js

import { Controller } from '@hotwired/stimulus';
import { getComponent } from '@symfony/ux-live-component';
import Modal from 'bootstrap/js/dist/modal';

export default class extends Controller {

    modal = null;

    async initialize() {
        this.modal = this.element;
    }

    connect() {
        window.addEventListener('modal:close', () => $(this.modal).modal('hide'));

        window.addEventListener('modal:show', () => $(this.modal).modal('show'));
    }

    show() {
        $(this.modal).modal('show');
    }
}

Le ModalComponent.php

Les paramètres à passer sont :

  • title : Le titre affiché dans la modale
  • entity : le nom de l'entité à utiliser
  • action : action à effectuer sur l'entité : create, update, delete, show
  • id : Id de l'item à récupérer : null si action=create
<?php

namespace App\Twig\live\component\modal;

use App\Controller\AbstractController;
use App\Entity\Parameter;
use App\Service\FormService;
use App\Service\FunctionsService;
use App\Service\NotificationService;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Contracts\Translation\TranslatorInterface;
use Symfony\UX\LiveComponent\Attribute\AsLiveComponent;
use Symfony\UX\LiveComponent\Attribute\LiveArg;
use Symfony\UX\LiveComponent\Attribute\LiveListener;
use Symfony\UX\LiveComponent\Attribute\LiveProp;
use Symfony\UX\LiveComponent\ComponentToolsTrait;
use Symfony\UX\LiveComponent\ComponentWithFormTrait;
use Symfony\UX\LiveComponent\DefaultActionTrait;
use Symfony\UX\LiveComponent\LiveResponder;
use Symfony\UX\LiveComponent\ValidatableComponentTrait;
use Symfony\UX\TwigComponent\Attribute\ExposeInTemplate;

#[AsLiveComponent('live:modal:modal', csrf: true)]
final class ModalComponent extends AbstractController
{
    use DefaultActionTrait,
        ValidatableComponentTrait,
        ComponentToolsTrait,
        ComponentWithFormTrait;

    protected  ?Request $request;

    #[ExposeInTemplate]
    public string $title = '';

    #[LiveProp]
    public ?Parameter $initialFormData = null;

    private string $action = '';
    private string $entity = '';
    private ?string $id = null;
    private string $url = '';

    public function __construct(
        RequestStack $requestStack,
        EntityManagerInterface $entityManager,
        Security $security,
        FunctionsService $functionsService,
        TranslatorInterface $translator,
        NotificationService $notificationService,
        public FormService $formService,
    )
    {
        parent::__construct($requestStack, $entityManager, $security, $functionsService, $translator, $notificationService);
    }

    public function mount():void
    {
    }

    #[LiveListener('modalShow')]
    public function show(
        #[LiveArg] string $title,
        #[LiveArg] string $action,
        #[LiveArg] string $entity,
        #[LiveArg] ?string $id,
        #[LiveArg] string $url,
        LiveResponder $responder
    ): void
    {
        $this->title = $title;
        $this->action = $action;
        $this->entity = $entity;
        $this->id = $id;
        $this->url = $url;

        $responder->dispatchBrowserEvent('modal:show', [
        ]);
    }

    protected function instantiateForm(): FormInterface
    {
        return $this->formService->createForm($this->entity, $this->action, $this->id);

//        return $this->createForm(ParameterType::class, $this->initialFormData);
    }
}

Et enfin dans ma page j'appelle le component :

<button
                data-click="open-modal"
                class="btn btn-sm btn-warning"
                onclick="document.getElementById('modal_display_item')
                .__component
                .emit('modalShow', {
                    title: '{{ "Edit event" |trans |escape('js') }}',
                    action: 'create',
                    entity: 'event',
                    id: null,
                }); return false;"
>test modal</button>

Dans le code, je vois que vous utilisez Stimulus pour gérer l'affichage des modales. Est-ce que tu l'as bien configuré ou bien importé ?

Bonjour,

Oui l'affichage de la modal se fait très bien. Ce que je n'arrive pas à faire est l'affichage et la gestion du FormType.

Dans ton composant ModalComponent.php, si j'ai bien compris, tu utilises la méthode instantiateForm pour créer le formulaire.

Assure-toi que la méthode renvoie le formulaire Symfony approprié pour l'entité et l'action que tu souhaites faire.

Tu peux essayer via le service FormService que tu as injecté.

Essaye le code suivant : <div class="modal fade" id="modal_display_item" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">{{ title }}</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
{{ form(form) }}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Fermer</button>
<button type="button" class="btn btn-primary" data-action="modal#submit">Enregistrer</button>
</div>
</div>
</div>
</div>

J'ai l'impression que tu n'as pas terminé la construction de ton formulaire.
Tu souhaite avoir un seul formType qui dépend se reproduire plusieurs fois selon le bouton sélectionné.

Oui il faut donc passer par l'id de ton objet et l'envoyer en javascript/jquery/react etcc.

Cependant je vois que ton buton à un id null.
Essaie de nous donner plus d'information qu'on puisse t'aider étape par étape.
Envoie nous le résultat de ta page sans omettre de regarder dans la console de ton navigateur.