Symfony: Как я могу отображать и обрабатывать много форм редактирования на странице подписи - PullRequest
0 голосов
/ 28 февраля 2019

Я застрял со следующей проблемой.

Я использую Symfony 4.2.3 для создания форума (часть большого проекта)

Я создал ForumControllerкто обрабатывает:

  • Домашняя страница форума (показать форум категории с их подкатегориями форума)
  • Страница категории форума (показать выбранную категорию форума с ее форумом подкатегории)
  • Страница подкатегории форума (показать выбранную категорию форума с ее темами форума)
  • Страница темы форума (показать выбранную тему форума с ее сообщением форума (то есть реакцией))

Я хочу реализовать кнопку редактирования, на которую не перенаправляютсястраница редактирования, но $ (this). свернула форму редактирования в div.Эта кнопка отображается, только если автор ForumMessage является текущим пользователем.Так что, если этот пользователь много раз отвечал на тему, мне нужно столько же кнопок (и формы).После нажатия на правку страницу можно перезагрузить и обновить сущность.

Для создания / редактирования с перенаправлением я понял, как это сделать.

Проблема заключалась в том, как обрабатывать неизвестное числоредактировать форму MessageType (и так неизвестный идентификатор формы).

Я пытаюсь создать массив ссылки ForumMessage на массив формы MessageType.Но когда мне нужно передать .createView () каждой формы ветке, мой мозг ломает.

Так что, пожалуйста, как я могу иметь много форм редактирования на странице подписи (каждая ссылка на указанную сущность) и обрабатыватьих в моем контроллере для модификации .flush?

Я уже реализую функцию JS для отображения кнопки и связанного div.

Метод showTopic моего ForumController.php:

/**
 * @Route("/forum/category={idCategory}/subCategory={idSubCategory}/topic={idTopic}", name="topic")
 * @ParamConverter("topic", options={"id" = "idTopic"})
 * @param $idCategory
 * @param $idSubCategory
 * @param $idTopic
 * @param Request $request
 * @param ObjectManager $manager
 * @param UserInterface $user
 * @return \Symfony\Component\HttpFoundation\Response
 * @throws \Exception
 */
public function showTopic($idCategory, $idSubCategory, $idTopic, Request $request, ObjectManager $manager, UserInterface $user = null) {
    $topic = $this->getDoctrine()->getRepository(ForumTopic::class)->find($idTopic);
    $userMessages = $this->getDoctrine()->getRepository(ForumMessage::class)->findBy([
        'author' => "Kaarie",
        'forumTopic' => $topic
    ]);

    // Nouveau message sur un topic
    $message = new ForumMessage();
    $form = $this->createForm(ForumMessageType::class, $message);
    $form->handleRequest($request);
    if($form->isSubmitted() && $form->isValid()) {
        $message->setAuthor($user->getUsername())
                ->setCreatedAt(new \DateTime())
                ->setForumTopic($topic);
        $manager->persist($message);
        $manager->flush();

        return $this->redirectToRoute('topic', [
            'idCategory' => $idCategory,
            'idSubCategory' => $idSubCategory,
            'idTopic' => $topic->getId(),
        ]);
    }

    // Editer un message
    $editMessage = new ForumMessage();
    $editForm = $this->createForm(ForumMessageType::class, $editMessage);
    $editForm->handleRequest($request);
    if($editForm->isSubmitted() && $editForm->isValid()) {
        $manager->persist($editMessage);
        $manager->flush();

        return $this->redirectToRoute('topic', [
            'idCategory' => $idCategory,
            'idSubCategory' => $idSubCategory,
            'idTopic' => $topic->getId(),
        ]);
    }

    return $this->render('forum/showTopic.html.twig',[
        'idCategory' => $idCategory,
        'idSubCategory' => $idSubCategory,
        'topic' => $topic,
        'messageForm' => $form->createView(),
        'editForm' => $editForm->createView(),
        'userMessage' => $userMessages,
    ]);
}

Класс MessageType в MessageType.php

class ForumMessageType extends AbstractType
{
   public function buildForm(FormBuilderInterface $builder, array $options)
   {
      $builder
        ->add('content')
        ->add('submit', SubmitType::class)
    ;
   }

   public function configureOptions(OptionsResolver $resolver)
   {
      $resolver->setDefaults([
        'data_class' => ForumMessage::class,
      ]);
   }
}

Часть ветки, которая отображает сообщение из showTopic.html.twig

    <ul>
        {% for message in topic.ForumMessages %}
            <li>
                {{ message.author }},</br>
                {{ message.content }}
                {% if app.user %}
                    {% if is_granted("ROLE_MODERATOR") %}

                        <button>Moderate</button> {# TODO: moderation d'un message #}
                    {% endif %}
                    {% if app.user.username == message.author %}
                        <div  class="alert alert-danger" style="margin: 1em; display: none">
                            <h3>Etidé votre réponse :</h3>
                            {{ form_start(editForm) }}
                            {{ form_row(editForm.content) }}
                            {{ form_row(editForm.submit, {'label': 'Editer'}) }}
                            {#<button type="submit" class="btn btn-primary">Editer</button>#}
                            {{ form_end(editForm) }}
                        </div>
                        <button id="buton_EditTopic">Modifier</button>
                    {% endif %}
                {% endif %}
            </li>
        {% endfor %}
    </ul>

Для любых других ресурсов, пожалуйста, спросите меня!

1 Ответ

0 голосов
/ 01 марта 2019

Мой подход был бы (возможно, необходима некоторая подстройка, не проверял)

Краткое объяснение: список будет содержать только контейнеры.Когда вы редактируете одно сообщение, вы загружаете только форму и отправляете ее в этот конкретный контейнер.Если вы отредактируете это и нажмете «Сохранить», он отправит форму в соответствии с ajax-запросом контроллеру.Если форма верна, она вернет json-ответ вместо html ...

Контроллер:

/**
 * @Route("/forum/category={idCategory}/subCategory={idSubCategory}/topic={idTopic}", name="topic")
 * @ParamConverter("topic", options={"id" = "idTopic"})
 * @param $idCategory
 * @param $idSubCategory
 * @param $idTopic
 * @param Request $request
 * @return \Symfony\Component\HttpFoundation\Response
 * @throws \Exception
 */
public function showTopic(
    $idCategory, 
    $idSubCategory, 
    $idTopic, 
    Request $request, 
    ObjectManager $manager, 
    UserInterface $user = null
)
{
    $topic = $this->getDoctrine()->getRepository(ForumTopic::class)->find($idTopic);
    $userMessages = $this->getDoctrine()->getRepository(ForumMessage::class)->findBy([
        'author' => "Kaarie",
        'forumTopic' => $topic
    ]);

    return $this->render('forum/showTopic.html.twig',[
        'idCategory' => $idCategory,
        'idSubCategory' => $idSubCategory,
        'topic' => $topic,
        'userMessage' => $userMessages,
    ]);
}

/**
 * With this, you can create and mod Topics
 * @Route("/forum/messages/{forumMessage}/mod-message", name="message.mod", defaults={"forumMessage":0})
 * @IsGranted("ROLE_USER")
 * @param Request $request
 * @param ForumMessage $forumMessage
 * @return mixed
 */
public function modTopic(
    Request $request, 
    Objectmanager $manager, 
    ForumMessage $forumMessage=null
)
{

    if($formMessage == null) {
        $forumMessage = new ForumMessage();
        /* set Additional Info here, maybe User, IP Adress or whatever */
    }
    $editForm = $this->createForm(ForumMessageType::class, $forumMessage);
    $editForm->handleRequest($request);
    if($editForm->isSubmitted() && $editForm->isValid()) {
        $manager->persist($forumMessage);
        $manager->flush();

        return new JsonRepsonse(['status'=>true, 'message' => "ForumMessage save successfull"]);
    }


    return $this->render('mod.message.html.twig',[
        'messageForm' => $editForm->createView(),
    ]);
}

FormType:

class ForumMessageType extends AbstractType
{
   public function buildForm(FormBuilderInterface $builder, array $options)
   {
      $builder
        ->add('content')
    ;
   }

   public function configureOptions(OptionsResolver $resolver)
   {
      $resolver->setDefaults([
        'data_class' => ForumMessage::class,
      ]);
   }
}

list.html.twig

<ul>
    {% for message in topic.ForumMessages %}
        <li>
            {{ message.author }},</br>
            {{ message.content }}
            {% if app.user %}
                {% if is_granted("ROLE_MODERATOR") %}

                    <button>Moderate</button> {# TODO: moderation d'un message #}
                {% endif %}
                {% if app.user.username == message.author %}
                    <div id="modMessageContainer{{ message.id }}"  class="alert alert-danger" style="margin: 1em; display: none">
                    </div>
                    <button onclick="modMessage(this);" 
                         data-attr-url="{{ path('message.mod'.{'forumMessage':message.id}) }}" 
                         data-attr-container="#modMessageContainer{{ message.id }}"
                    >Modifier</button>
                {% endif %}
            {% endif %}
        </li>
    {% endfor %}
</ul>
<script>
    function modMessage(element)
    {
        $.ajax({
            url: $(element).attr('data-attr-url'),
            success: function(data) {
                $($(element).attr('data-attr-container')).html(data).show();
            }
        });
    }

    function saveMessage(element)
    {
        var container = $(element).attr('data-attr-container');
        $.ajax({
            url: $(element).attr('data-attr-url'),
            type:'POST',
            data: $(container +' form').serialize(),
            success: function(data) {
                if(typeof data == 'object' && data instanceof Object && !(data instanceof Array)) {
                    if(data.status) {
                        location.reload()
                    } else {
                        alert(data.message);
                    }
                } else {
                    $(container).show();
                    $('#modMessage').replaceWith($(data).find('#modMessage'));
                }
            }
        });
    }
</script>

mod.html.twig

<div>
    <div id="modMessage">
        <h3>Etidé votre réponse :</h3>
        {{ form_start(editForm) }}
        {{ form_row(editForm.content) }}
        {{ form_row(editForm.submit, {'label': 'Editer'}) }}
        {#<button type="submit" class="btn btn-primary">Editer</button>#}
        {{ form_end(editForm) }}
        <div style="text-align:right">
            <button onclick="saveMessage(this);" 
                 type="button" 
                 class="btn btn-success" 
                 data-attr-container="modMessageContainer{{ message.id }}" 
                 data-attr-url="{{ path('message.mod', {'forumMessage':message.id}) }}"
             >Save</button>
        </div>
    </div>
</div>
...