我是Symfony的新手,所以我開始使用官方教程,安裝了Symfony框架3.3.2,並在定製實體,控制器,形式和對我的具體需求的看法。Symfony 3.3:無法添加和刪除與收集表單類型相同的實體的項目
所以基本上我有一個名爲BasePreset的實體,在數據庫中已經有了幾行,並且我最終設法創建了一個表單集合類型,該類型使用'add'和''來呈現可編輯BasePreset實體字段的列表。刪除'鏈接:第一個將新的空白字段添加到列表中,並且每個「刪除」鏈接都會從DOM中刪除相應的字段。根據文檔的一切。
所以,我成功地更新了現有的字段(我看到在重新加載後,以及在數據庫中的HTML格式正確的更改)。
問題是,添加/刪除不起作用。沒有錯誤給出。檢入Chrome開發工具:按預期發送參數。
我以前關於表單生成以下文件(和很多課程的谷歌搜索):現在
http://symfony.com/doc/current/forms.html
https://symfony.com/doc/current/best_practices/forms.html
https://symfony.com/doc/current/form/form_collections.html
https://symfony.com/doc/current/reference/forms/types/collection.html
,在this doc陳述爲:
您必須同時創建addTag()和removeTag()方法,否則 即使by_reference爲false,表單仍將使用setTag()。您將在本文後面的章節中詳細瞭解removeTag()方法。
在這一刻我沒有任何引用子實例,因爲它在示例中描述。我只希望能夠編輯相同的普通實體,包括添加新項目和刪除現有項目。也許我錯了,但這在我看來似乎是一個微不足道的基本目標。我不明白如何正確添加'setBasePreset'和'removeBasePreset'方法到'BasePreset'實體本身。
當然,我可以跳過使用表單生成器,但我想利用它的力量作爲框架的一部分。任何建議,例如,可能指向我錯過了一些相關的文檔/教程 - 將不勝感激。
張貼例如(具有一個加法和一個去除):
base_presets[base_presets][5][name]:new_preset
base_presets[base_presets][5][description]:new, not really added
base_presets[base_presets][0][name]:ffffas44432df
base_presets[base_presets][0][description]:asdfffff2333
base_presets[base_presets][2][name]:ffffasdf2222
base_presets[base_presets][2][description]:asdff3fff2333
base_presets[base_presets][3][name]:yoyoshka
base_presets[base_presets][3][description]:nananaf
base_presets[base_presets][4][name]:123fffdsaasdf
base_presets[base_presets][4][description]:pop123
base_presets[_token]:H2QwRHdvZW1WAdc6VTONnspxvH1U-oC8rCEEprDdMCQ
的 'BasePresetsType' 類:
<?php
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
class BasePresetsType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('base_presets', CollectionType::class, array(
'entry_type' => BasePresetType::class,
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false // also tried 'true' but without any success
));
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => null,
));
}
}
的 'BasePresetType' 類:
<?php
namespace AppBundle\Form;
use AppBundle\Entity\BasePreset;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
class BasePresetType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('name', TextType::class)
->add('description', TextareaType::class);
}
public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults([
'data_class' => BasePreset::class,
]);
}
}
控制器方法:
的觀點:
{% extends "base.html.twig" %}
{% block body %}
{{ form_start(form) }}
{{ form_label(form.base_presets) }}
{{ form_errors(form.base_presets) }}
<ul class="base-presets" data-prototype="{{ form_widget(form.base_presets.vars.prototype)|e('html_attr') }}">
{% for base_preset in form.base_presets %}
<li class="base-preset-item">
{{ form_errors(base_preset) }}
{{ form_widget(base_preset) }}
</li>
{% endfor %}
<li class="form-submit">
<input type="submit" value="Submit" class="btn btn-default pull-right" />
</li>
</ul>
{{ form_end(form) }}
{% endblock %}
{% block javascripts %}
<script>
var $collection_holder;
// Setup an "add a base preset" link
var $add_base_preset_link = $('<a href="#" class="add_base_preset_link">Add a base preset</a>');
var $new_link_li = $('<li></li>').append($add_base_preset_link);
$(document).ready(function() {
// Get the ul that holds the collection of base presets
$collection_holder = $('ul.base-presets');
// add the "add a base preset" anchor and li to the tags ul
$collection_holder.prepend($new_link_li);
// count the current form inputs we have, use that as the new index when inserting a new item
$collection_holder.data('index', $collection_holder.find('li.base-preset-item').length);
$add_base_preset_link.on('click', function (e) {
e.preventDefault();
addBasePresetForm($collection_holder, $new_link_li);
});
// add a delete link to all of the existing base presets form li elements
$collection_holder.find('li.base-preset-item').each(function() {
addBasePresetFormDeleteLink($(this));
});
});
function addBasePresetForm($collection_holder, $new_link_li) {
// Get the data-prototype
var prototype = $collection_holder.data('prototype');
// Get the new index
var index = $collection_holder.data('index');
// Replace '__name__' in the prototype's HTML to instead be a number based on how many items we have
var new_form = prototype.replace(/__name__/g, index);
// increment the index for the next item
$collection_holder.data('index', index + 1);
// Display the form in the page in an li, before the "Add a base preset" link li
var $new_form_li = $('<li class="base-preset-item"></li>').append(new_form);
$new_link_li.after($new_form_li);
addBasePresetFormDeleteLink($new_form_li);
}
function addBasePresetFormDeleteLink($base_preset_form_li) {
var $remove_form_a = $('<a href="#">Delete this base preset</a>');
$base_preset_form_li.append($remove_form_a);
$remove_form_a.on('click', function (e) {
e.preventDefault();
$base_preset_form_li.remove();
})
}
</script>
{% endblock %}
最後,最長的清單 - 在 'BasePreset' 實體類:
<?php
namespace AppBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
/**
* Class BasePreset
* @package AppBundle\Entity
*
* @ORM\Entity
* @ORM\Table(name="base_presets")
* @UniqueEntity(fields="name", message="There should be only one (unique) base preset")
*/
class BasePreset {
/**
* @ORM\OneToMany(targetEntity="BaseParamsGroup", mappedBy="base_preset")
*/
private $base_params_groups;
/**
* @var int
*
* @ORM\Column(type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(type="string", length=100)
*/
private $name;
/**
* @var string
*
* @Assert\NotBlank()
* @ORM\Column(type="string", length=4000)
*/
private $description;
/**
* @var \DateTime
*
* @ORM\Column(type="datetime")
*/
private $created;
/**
* @var \DateTime
*
* @ORM\Column(type="datetime", columnDefinition="TIMESTAMP on update CURRENT_TIMESTAMP")
*/
private $updated;
public function __construct() {
$this->base_params_groups = new ArrayCollection();
$this->created = new \DateTime();
$this->updated = new \DateTime();
}
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* @param string $name
*
* @return BasePreset
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Set description
*
* @param string $description
*
* @return BasePreset
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description
*
* @return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set created
*
* @param \DateTime $created
*
* @return BasePreset
*/
public function setCreated($created)
{
$this->created = $created;
return $this;
}
/**
* Get created
*
* @return \DateTime
*/
public function getCreated()
{
return $this->created;
}
/**
* Set updated
*
* @param \DateTime $updated
*
* @return BasePreset
*/
public function setUpdated($updated)
{
$this->updated = $updated;
return $this;
}
/**
* Get updated
*
* @return \DateTime
*/
public function getUpdated()
{
return $this->updated;
}
/**
* Add baseParamsGroup
*
* @param \AppBundle\Entity\BaseParamsGroup $baseParamsGroup
*
* @return BasePreset
*/
public function addBaseParamsGroup(\AppBundle\Entity\BaseParamsGroup $baseParamsGroup)
{
$this->base_params_groups[] = $baseParamsGroup;
return $this;
}
/**
* Remove baseParamsGroup
*
* @param \AppBundle\Entity\BaseParamsGroup $baseParamsGroup
*/
public function removeBaseParamsGroup(\AppBundle\Entity\BaseParamsGroup $baseParamsGroup)
{
$this->base_params_groups->removeElement($baseParamsGroup);
}
/**
* Get baseParamsGroups
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getBaseParamsGroups()
{
return $this->base_params_groups;
}
}
它適用於添加新行,但不適用於刪除現有行(仍然沒有錯誤,只是沒有更改)。它可以解決嗎?也許我應該創建一些集合類,將它作爲Data類放入集合表單類型中? – a1111exe
@ a1111exe您可以將'$ base_presets'中的ID與提交的ID進行比較,然後分別調用'$ em-> remove($ notSubmittedEntity);'。 – jkucharovic
我顯然可以,也許應該這樣做。我很好奇,如果這是唯一的方法。例如,對於官方示例中的subentity,不需要這樣做。這個解決方案看起來像一個微妙的黑客,以減少表單系統的一些缺乏靈活性。無論如何,我必須繼續前進,所以它會爲我工作。您能否將此添加到您的答案中,以便將其標記爲已接受? – a1111exe