I am trying to save entities of 2 classes in 1 form I have read this article about it. My code is :
class MeetingType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('meetingDay', 'text', array('label' => 'Dzień zbiórki'))
->add('meetingTime', 'text', array('label' => 'Godzina zbiórki'))
->add('congregation', 'entity', array(
'class' => 'ViszmanCongregationBundle:Congregation',
'property' => 'name', 'label' => 'Zbór'
));
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Viszman\CongregationBundle\Entity\Meeting'
));
}
/**
* #return string
*/
public function getName()
{
return 'viszman_congregationbundle_meeting';
}
}
And another TYPE:
class CongregationType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$plDays = array('day1', 'day1', 'day1', 'day1', 'day1', 'day1', 'day1');
$builder
->add('name', 'text', array('label' => 'Name'))
->add('meetingDay', 'choice', array('label' => 'meeting day', 'choices' => $plDays))
->add('meetings','collection', array('type' => new MeetingType(), 'allow_add' => true))
;
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Viszman\CongregationBundle\Entity\Congregation'
));
}
/**
* #return string
*/
public function getName()
{
return 'viszman_congregationbundle_congregation';
}
}
And when I try do render this form I only get CongregationType and no MeetingType form. part of code responsible for rendering form is:
<h1>Congregation creation</h1>
{{ form_start(form) }}
{{ form_widget(form) }}
<h3>Meetings</h3>
<ul class="tags" data-prototype="{{ form_widget(form.meetings.vars.prototype)|e }}">
{{ form_widget(form.meetings) }}
</ul>
{{ form_end(form) }}
If I remember correctly the entity form field is used to reference an existing entity, not to create a new one.
This is not what you need, what you need is embedded forms, take a look at the symfony book.
Related
My application show this error
Type error: Too few arguments to function AppBundle\Form\ActualiteType::__construct(), 0 passed in /Applications/MAMP/htdocs/SyndicNous/vendor/symfony/symfony/src/Symfony/Component/Form/FormRegistry.php on line 90 and exactly 2 expected
My formType
class ActualiteType extends AbstractType
{
/**
* #var bool $admin
*/
private $admin;
/**
* #var User $user
*/
private $user;
/**
* ActualiteType constructor.
* #param bool|false $admin
*/
public function __construct($admin = false, $user)
{
$this->admin = $admin;
$this->user = $user;
}
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$categories = array(
'Travaux' => 'Travaux',
'Voisinage' => 'Voisinage',
);
$builder
->add('title')
->add('category')
->add('content')
->add('datePublish')
->add('category', ChoiceType::class, array(
'choices' => $categories
)
);
if ($this->user->getResidence() != null) {
$builder->add('residence', EntityType::class, array(
'class' => 'AppBundle:Residence',
'choices' => $this->user->getResidence(),
));
} else {
$builder->add('residence', 'entity', array(
'class' => 'AppBundle:Residence',
'choice_label' => 'name'
));
};
}
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Actualite'
));
}
/**
* {#inheritdoc}
*/
public function getBlockPrefix()
{
return 'appbundle_actualite';
}
}
Do you have any idea where the problem would come from? Thank you
I do not understand what you're trying to do. You do not need to use the constructor to pass parameters to your formType. There is the second parameter of the buildForm method for this ($options).
In your controller, create your form like this :
$form = $this->createForm(ActualiteType::class, $actualite, [
'admin' => $admin,
'user' => $user
]);
And modify your formType like that :
class ActualiteType extends AbstractType {
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$admin = $options['admin']; // Not used ?
$user = $options['user'];
$categories = array(
'Travaux' => 'Travaux',
'Voisinage' => 'Voisinage',
);
$builder->add('title')
->add('category')
->add('content')
->add('datePublish')
->add('category', ChoiceType::class, array(
'choices' => $categories
)
);
if ($user->getResidence() != null) {
$builder->add('residence', EntityType::class, array(
'class' => 'AppBundle:Residence',
'choices' => $user->getResidence(),
));
} else {
$builder->add('residence', 'entity', array(
'class' => 'AppBundle:Residence',
'choice_label' => 'name'
));
};
}
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Actualite',
'admin' => null, // Default
'user' => null // Default
));
}
}
Do not forget to put the default values of your options in configureOptions method.
I have created a form with doctrine. It works if I do not pass any option, like this:
$builder
->add('name')
->add('password', 'password')
->add('password_repeat', 'password')
->add('email', 'email')
->add('save', 'submit')
;
But, if I add an array with options as it says the docs (http://symfony.com/doc/current/book/forms.html#book-form-creating-form-classes), I get an error that says:
Expected argument of type "string or Symfony\Component\Form\FormTypeInterface", "array" given
This is the formtype created by doctrine:
<?php
namespace MainBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class UserType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name') //if I put ->add('name', array('label' => 'Your name')) I get the error
->add('password', 'password')
->add('password_repeat', 'password')
->add('email', 'email')
->add('save', 'submit')
;
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'MainBundle\Entity\User'
));
}
/**
* #return string
*/
public function getName()
{
return 'mainbundle_user';
}
}
You must specify the type of your field before adding options
$builder->add('name', 'text', array('label' => 'Your name'))
For the Symfony version 3+ it should be ,
$builder->add('name', TextType::class, array('label' => 'Your name'))
I created a custom form field type "duration", and 2 fields "hour" and "minutes"
class DurationType extends AbstractType
{
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults([]);
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('hours', new DurationSmallType(), [])
->add('minutes', new DurationSmallType(), [])
;
}
public function finishView(FormView $view, FormInterface $form, array $options)
{
}
public function getName()
{
return 'duration';
}
}
DurationSmallType:
class DurationSmallType extends AbstractType
{
public function getName()
{
return 'duration_small';
}
}
Template for both types:
{% block duration_small_widget -%}
<div class="input-group" style="display: inline-block;width:100px;height: 34px;margin-right: 20px;">
<input type="text" {{ block('widget_attributes') }} class="form-control" style="width:50px;" {% if value is not empty %}value="{{ value }}" {% endif %}>
<span class="input-group-addon" style="height: 34px;"></span>
</div>
{%- endblock duration_small_widget %}
{% block duration_widget -%}
{{ form_widget(form.hours) }}
{{ form_widget(form.minutes) }}
{%- endblock duration_widget %}
In Entity duration saved in minutes (as integer) and I create a DataTransformer in form builder:
class EventType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$dataTransformer = new DurationToMinutesTransformer();
$builder
->add('name', NULL, array('label' => 'Название'))
->add('type', NULL, array('label' => 'Раздел'))
->add($builder
->create('duration', new DurationType(), array('label' => 'Продолжительность'))
->addModelTransformer($dataTransformer)
)
->add('enabled', NULL, array('label' => 'Включено'));
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'TourConstructor\MainBundle\Entity\Event',
'csrf_protection' => true,
'csrf_field_name' => '_token',
'intention' => 'events_token'
));
}
/**
* #return string
*/
public function getName()
{
return 'mybundle_event';
}
}
DurationToMinutesTransformer:
class DurationToMinutesTransformer implements DataTransformerInterface
{
public function transform($value)
{
if (!$value) {
return null;
}
$hours = ceil($value / 60);
$minutes = $value % 60;
return [
"hours" => $hours,
"minutes" => $minutes
];
}
public function reverseTransform($value)
{
if (!$value) {
return null;
}
return $value["hours"]*60 + $value["minutes"];
}
}
Transform - work, I have hours and minutes in edit field, but reverseTransform doesn't work, after submit I have duration field as Array.
Symfony error:
Symfony\Component\Validator\ConstraintViolation
Object(Symfony\Component\Form\Form).children[duration].children[hours] = 3
Caused by:
Symfony\Component\Form\Exception\TransformationFailedException
Compound forms expect an array or NULL on submission.
Symfony\Component\Validator\ConstraintViolation
Object(Symfony\Component\Form\Form).children[duration].children[minutes] = 0
Caused by:
Symfony\Component\Form\Exception\TransformationFailedException
Compound forms expect an array or NULL on submission.
Please, help me.
I find error, DurationSmallType need option compound=false, default is true and symfony try to use my 2 field as inside form.
And I remove modelTransformer from entity form and place it in DurationType.
Finaly code of my forms builders:
EventType:
class EventType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$dataTransformer = new DurationToMinutesTransformer();
$builder
->add('name', NULL, array('label' => 'Название'))
->add('type', NULL, array('label' => 'Раздел'))
->add($builder
->create('duration', new DurationType(), array('label' => 'Продолжительность'))
->addModelTransformer($dataTransformer)
)
->add('enabled', NULL, array('label' => 'Включено'));
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'TourConstructor\MainBundle\Entity\Event',
'csrf_protection' => true,
'csrf_field_name' => '_token',
'intention' => 'events_token'
));
}
/**
* #return string
*/
public function getName()
{
return 'mybundle_event';
}
}
DurationType:
class DurationType extends AbstractType
{
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'html5' => true,
'error_bubbling' => false,
'compound' => true,
));
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('hours', new DurationSmallType(), [
"label"=>"ч."
])
->add('minutes', new DurationSmallType(), [
"label"=>"мин."
])
->addViewTransformer(new DurationToMinutesTransformer())
;
}
public function finishView(FormView $view, FormInterface $form, array $options)
{
}
public function getName()
{
return 'duration';
}
}
DurationSmallType:
class DurationSmallType extends AbstractType
{
/**
* {#inheritdoc}
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'compound' => false,
));
}
public function getName()
{
return 'duration_small';
}
}
I have a Timeslot functionality where the user has to be able to edit the start and end of each slot.
So I would like to create one form that contains alle timeslots. I based my code on this article in symfony docs: http://symfony.com/doc/current/cookbook/form/form_collections.html
The problem is that in this article, there's some kind of parent entity to which the collection instances should be assigned to. In my case, the timeslots are standalone and do not have a relation with another entity (that is relevent at this stage).
So.. my question: How do I create a collection of forms with my timeslots?
Controller.php
/**
* #Route("/settings", name="settings")
* #Template()
*/
public function settingsAction()
{
$timeslots = $this->getDoctrine()->getRepository("ScheduleBundle:Timeslot")->findAll();
$timeslots_form = $this->createFormBuilder()
->add('timeslots', 'collection', array(
'type' => new TimeslotType(),
))
->add('save', 'submit')
->getForm();
return array(
'timeslots' => $timeslots_form->createView()
);
}
TimeslotType.php:
class TimeslotType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('start', 'time', array(
'input' => 'datetime',
'widget' => 'choice',
))
->add('end', 'time', array(
'input' => 'datetime',
'widget' => 'choice',
))
;
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Oggi\ScheduleBundle\Entity\Timeslot'
));
}
/**
* #return string
*/
public function getName()
{
return 'timeslot';
}
}
Any thoughts?
thanks in advance!
Pass an array instead of an entity to your form. The form can process either just fine.
$timeslots = $this->getDoctrine()->getRepository("ScheduleBundle:Timeslot")->findAll();
$formData = array('timeslots' => $timeslots);
$timeslots_form = $this->createFormBuilder($formData) ...
I've been stuck on this for quite some time now. I read quite some answers here on SO but I couldn't get it running.
My controller contains
$series = $this->getDoctrine()->getRepository('DemoDemoBundle:Series')->createQueryBuilder('series')
->where('series.type = 1')
->getQuery()->getResult();
$magazine = new Magazine();
$content = array(
'series' => $series
);
$form = $this->createForm(new MagazineType($this->get('translator'), $content), $magazine);
$form->handleRequest($request);
I would like to pass the variable $content to the form so that 'series' can be used in some selectboxes. MagazineType extends PublicationType. The same goes for the underlying entities. Here's how MagazineType looks:
class MagazineType extends PublicationType
{
function __construct($translator, array $series = null)
{
parent::__construct($translator, $series); //$series);
}
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
// TODO: Refactor constant out
parent::buildForm($builder, $options)
// ->add('dateSubmitted')
// ->add('userSubmitted')
// ->add('file')
->add('issueNumber')
->add('save', 'submit');
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(
array(
'data_class' => 'Demo\DemoBundle\Entity\Magazine',
'series' => $this->translator->trans('addPublication.noSeries')
)
);
}
and PublicationType
class PublicationType extends AbstractType
{
protected $series, $translator;
public function __construct($translator, $series)
{
$this->translator = $translator;
$this->series = $series;
}
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options){
$builder
->add('name', 'text', array(
'label' => $this->translator->trans('addPublication.name')
))
// ->add('dateSubmitted')
// ->add('userSubmitted')
// ->add('file')
->add('series', 'choice', $this->series);//$formOptions['series']);
;
return $builder;
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Demo\DemoBundle\Entity\Publication',
'series' => $this->translator->trans('addPublication.noSeries')
));
}
Maybe I'm accessing the series variable the wrong way, but I'm not even getting any further than constructing MagazineType (option series not allowed) even though I've set it in DefaultOptions as stated on http://symfony.com/doc/current/components/options_resolver.html#configure-allowed-types. I'm probably missing something here though similar questions, since I'm stuck on this the entire day.
Thx for any help!