#forms #symfony
#формы #symfony
Вопрос:
В моем проекте я хотел бы иметь возможность добавлять коллекцию в форму. Я думал о FormTypeCollection. Но дело в том, что мне нужно что-то подобное: кнопка «Создать» в конце формы, и каждый раз, когда вы нажимаете на новую, добавляется «мини-форма», и у вас есть три ввода для заполнения: «имя, текст, ссылка». Я бы хотел, чтобы он сохранялся в базе данных, например, как artists = [name,text,link]. Я понятия не имею, как это сделать. я не хочу добавлять исполнителя сущности, потому что мне это нужно только для отображения, и мне не нужно, чтобы он сохранялся как объект в базе данных. Мой код сейчас такой:
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->with('Contenu')
->add('published', CheckboxType::class, ['required' => false, 'label' => 'Publier'])
->add('title', TextType::class, ['required' => true, 'label' => 'Titre'])
->add('marketingEtiquette', TextType::class, ['required' => false, 'label' => 'Etiquette Marketing'])
->add('textLink', TextType::class, ['required' => true, 'label' => 'Texte du lien'])
->add('shoppingLink', TextType::class, ['required' => true, 'label' => 'Lien'])
->add('media', ElFinderType::class, array(
'label' => 'Photo',
'instance' => 'form',
'enable' => true,
'required' => true,
'attr' => array('class' => 'form-control')
)
)
->add('position',ChoiceType::class, array(
'label' => 'Position dans la page',
'choices' => array(
'Bloc Artistes' => 'artists',
'Bloc haut de page' => 'top',
'Bloc bas de page' => 'bottom'
)
))
->add('artists',CollectionType::class,array(
'label' => 'Les artistes',
'allow_add' => true,
))
->end();
}
Я не знаю, как добавить 3 поля к исполнителям полей и сгенерировать их при нажатии кнопки добавления. я даже не знаю, возможно ли это на самом деле. Я также не знаю, каким должен быть тип «исполнители» в базе данных.
РЕДАКТИРОВАТЬ: я хотел бы сделать что-то подобное, поэтому мне не нужно создавать объект или FormType:
->add('artists',CollectionType::class,array(
'entry_type' => TextType::class ,
'entry_options' => [
'artistName' => TextType::class,
'artistText' => TextType::class,
'artistLink' => TextType::class,
],
'label' => 'Les artistes',
'allow_add' => true,
'allow_delete' => true,
'delete_empty' => true,
'by_reference' => false
))
Но это не работает, поэтому, я думаю, я не могу. Ошибка:
The current field `artists` is not linked to an admin. Please create one for the target entity : ``
РЕДАКТИРОВАТЬ 2:
Я создал свой ArtistFormType:
class ArtistFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('artistName', TextType::class, array(
'label' => 'Nom de l'artiste'
))
->add('artistText', TextType::class, array(
'label' => 'Texte sous l'artiste'
))
->add('artistLink', TextType::class, array(
'label' => 'Lien vers l'artiste'
))
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => null,
]);
}
}
Я назвал это так:
->add('artists',CollectionType::class,array(
'entry_type' => ArtistFormType::class,
'label' => 'Les artistes',
'allow_add' => true,
'allow_delete' => true,
'delete_empty' => true,
'by_reference' => false
))
Но я получаю ту же ошибку:
The current field `artists` is not linked to an admin. Please create one for the target entity : ``
Ответ №1:
РЕДАКТИРОВАТЬ: это решение ограничено Symfony Component Form Extension Core Type CollectionType, оно может отличаться от решения от Sonata Admin.
Вы можете найти некоторую информацию об этом в документации.
«Самый простой» способ сделать это — создать другую форму (например, ArtistFormType) с полями, которые вы хотите добавить. Затем в вашей родительской форме вы добавляете CollectionType :
$formMapper
// ...
->add('artists', CollectionType::class, [
'entry_type' => ArtistFormType::class,
'label' => 'Artists',
'allow_add' => true,
'allow_delete' => true,
'delete_empty' => true,
'by_reference' => false
])
;
Затем, если у вас уже есть несколько исполнителей в вашей сущности, он будет отображать ArtistFormType один раз для каждого исполнителя.
Если вы хотите добавить новых исполнителей, это немного сложнее и требует некоторого Javascript.
Сначала отобразите коллекцию внутри <ul></ul>
тега :
<ul class="artists">
{{ form_row(form.artists) }}
</ul>
Следуя этому jsfiddle :
Найдите коллекцию и добавьте к ней кнопку «добавить исполнителя»
<script>
var $addArtistLink = $('<a href="#" class="add_artist_link">Add an artist</a>');
var $newLinkLi = $('<li></li>').append($addArtistLink);
jQuery(document).ready(function() {
// Get the ul that holds the collection of artists
var $collectionHolder = $('ul.artists');
// add the "add a tag" anchor and li to the tags ul
$collectionHolder.append($newLinkLi);
// ...
}
</script>
Добавьте событие «click» с некоторыми манипуляциями с dom, чтобы добавить новых исполнителей :
jQuery(document).ready(function() {
// ...
// count the current form inputs we have (e.g. 2), use that as the new
// index when inserting a new item (e.g. 2)
$collectionHolder.data('index', $collectionHolder.find(':input').length);
$addArtistLink.on('click', function(e) {
// prevent the link from creating a "#" on the URL
e.preventDefault();
// add a new artist form
addArtistForm($collectionHolder, $newLinkLi);
});
});
function addArtistForm($collectionHolder, $newLinkLi) {
// Get the data-prototype explained earlier
var prototype = $collectionHolder.data('prototype');
// get the new index
var index = $collectionHolder.data('index');
// Replace '$$name$$' in the prototype's HTML to
// instead be a number based on how many items we have
var newForm = prototype.replace(/__name__/g, index);
// increase the index with one for the next item
$collectionHolder.data('index', index 1);
// Display the form in the page in an li, before the "Add an artist" link li
var $newFormLi = $('<li></li>').append(newForm);
// also add a remove button
$newFormLi.append('<a href="#" class="remove-artist">x</a>');
$newLinkLi.before($newFormLi);
// handle the removal
$('.remove-artist').click(function(e) {
e.preventDefault();
$(this).parent().remove();
return false;
});
}
Тогда все должно работать нормально. Конечно, некоторые изменения могут быть внесены в соответствии с вашим проектом (имена полей, добавить кнопку удаления для существующих исполнителей, …).
Комментарии:
1. Большое спасибо за ваш ответ! Я пытаюсь, но для этого мне нужно создать объект Artist? Дело в том, что я бы не хотел создавать объект Artist. Возможно ли это? Или мне нужно создать объект?
2. Я думаю, что будет проще (и лучше) создать объект Artist с отношением ManyToOne к объекту основной формы. Если вы действительно не хотите создавать эту сущность, вы можете указать «‘data_class’ => null» в вашем ArtistFormType, и тогда данные будут нормализованы как массив, а не как объект.
3. Хорошо, потому что я думал, что смогу сделать что-то вроде того, что я сделал в своем редактировании, тогда это невозможно?
4. Так не получится. Я думаю, вам, по крайней мере, придется создать ArtistFormType . Кроме того, «entry_options» используется для установки параметров FormType в «entry_type», а не полей, как вы сделали в своем редактировании.
5. Хорошо, я сделал это, но не работает, я отредактировал свой вопрос ^^