Symfony4:具有ChoiceType的Collection(Type)的动态表单,其具有进一步的要求

时间:2019-10-28 21:02:35

标签: symfony4 dynamic-forms

对不起,我太愚蠢了,无法理解Symfony 4文档的这一部分。 我想生成一个表单来创建和编辑具有相关子集的数据集(通常是完全没有问题)。

第一个实体称为Case(此问题仅是一个属性)。

<?php
namespace App\Entity;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * @ORM\Entity(repositoryClass="App\Repository\CaseRepository")
 */
class Case
{
   // [...]

    /**
     * @ORM\Column(type="text", nullable=false)
     * @Assert\NotNull()
     * @var string
     */
    private $title;

    // [...]

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\CaseForecast", mappedBy="case",  cascade={"persist", "remove"},orphanRemoval=true)
     */
    private $caseForecasts;


    public function __construct()
    {
        // [...]
        $this->caseForecasts = new ArrayCollection();
    }

    // [...]

    /**
     * @return Collection|CaseForecast[]
     */
    public function getCaseForecasts(): Collection
    {
        return $this->caseForecasts;
    }

    public function addCaseForecastis(CaseForecast $caseForecastis): self
    {
        if (!$this->caseForecasts->contains($caseForecastis)) {
            $this->caseForecasts[] = $caseForecastis;
            $caseForecastis->setCase($this);
        }
        return $this;
    }

    public function removeCaseForecastis(CaseForecast $caseForecastis): self
    {
        if ($this->caseForecasts->contains($caseForecastis)) {
            $this->caseForecasts->removeElement($caseForecastis);
            // set the owning side to null (unless already changed)
            if ($caseForecastis->getCase() === $this) {
                $caseForecastis->setCase(null);
            }
        }
        return $this;
    }
}

此时的重要关系是CaseForecast。这是一个ManyToOne关系。 这是实体:

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\CaseForecastRepository")
 */
class CaseForecast
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Case", inversedBy="caseForecasts")
     * @ORM\JoinColumn(nullable=false)
     */
    private $case;

    /**
     * @ORM\Column(type="integer")
     */
    private $itemNumber;

    /**
     * @ORM\Column(type="integer", options={"comment":"0 secure; 1 fragile; 2 reject"})
     *
     */
    private $forecast;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $comment;

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getCase(): ?Case
    {
        return $this->case;
    }

    public function setCase(?Case $case): self
    {
        $this->case = $case;

        return $this;
    }

    public function getItemNumber(): ?int
    {
        return $this->itemNumber;
    }

    public function setItemNumber(int $itemNumber): self
    {
        $this->itemNumber = $itemNumber;
        return $this;
    }

    public function getForecast(): ?int
    {
        return $this->forecast;
    }

    public function setForecast(int $forecast): self
    {
        $this->forecast = $forecast;
        return $this;
    }

    public function getBegruendung(): ?string
    {
        return $this->begruendung;
    }

    public function setBegruendung(?string $begruendung): self
    {
        $this->begruendung = $begruendung;
        return $this;
    }

    public function __toString()
    {
        return $this->zahnNummer;
    }
}

属性itemNumber的取值范围为11..18,21..28,31..38,41..48 一个实体Case每次都有32个CaseForecast作为ArrayCollection ...每次! 当创建对象Case时,我还创建了32个对象CaseForecast。 属性“ forecast”是0,1或2的整数。

该表格应如下所示: Form with Collection of ChoiceTypes

您在图片上看到的内容:
左侧是预测值的换算值。
紧随其后的是CaseForecast.forecast,编号为11-18和28-21
在下一个“行”中,您会在两行中看到itemNumbers。
接下来的行编号为41-48和38-31的CaseForecast
(是的,您是对的,全都是假牙)

在第一步中,我手动创建了表单,因为数据模式不同(宽表/大对象为32)。现在,我不得不更改数据方案,现在我可以投降了。

我的FormType看起来像这样:

<?php

namespace App\Form;

use App\Entity\Case;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;

class CaseShortType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('titel', TextType::class, [
                'label' => "Title",
                'attr' => [
                    'tab-index' => 1
                ]
            ])
            ->add('caseForecasts', CollectionType::class, [
                'entry_type' => ChoiceType::class,
                'entry_options' => [
                    'choices' => [
                        'secure' => 0,
                        'fragile' => 1,
                        'reject' => 2
                    ],
                    'expanded' => true,
                ],
                'allow_add' => false,
                'allow_delete' => false,
            ])
            ->add("submit", SubmitType::class, [
                'label' => 'save',
                'attr' => ['class' => "btn btn-primary"]
            ]);
    }

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

我在symfony.com,stackoverflow等上尝试了一些教程和文档。我做完了,有点沮丧。什么都不适合,甚至不适合我。

我想要什么:

  • 我想以此从上面的屏幕创建表单 关系方案。
  • 我想以“ symfony-way”方式进行操作,而不是手动进行。
  • 当我编辑“ Case”时,我希望选择值已预先检查 来自CaseForecast.forecast(在choice_value上进行回调?如何访问 当前的CaseForecast?)
  • 我希望itemNumber作为关键字 CollectionType数组(如果无法通过这种方式工作,我必须 进行翻译)。

也许您对其他一些HowTo和文档有一些提示...

谢谢!

1 个答案:

答案 0 :(得分:0)

我自己解决了这个问题,感谢您的收听。

  1. 我创建了一个实体,并通过3种解决方案将ChoiceType更改为EntityType。我发现的示例始终基于EntityType。所以我用了这个。
  2. 我为集合的单个项目创建了一个ForecastType,并为“选中”比较添加了一个EventListener
  3. 对于布局,我为预测的子表单添加了自定义表单主题。
  4. 我更改了表单模板,将集合分为多个块:
methods: {
  handleFinalURL(value) {
    // do stuff here like
    callFunction(value, someOtherParam, extra)
  }
}

就是“全部”。当我提交表单并处理请求时,一切都在它所属的地方:)