I'have this fields on my enity to store two dates in unixtime format
/**
* #var \int
*
* #Gedmo\Timestampable(on="create")
* #ORM\Column(name="activation_date", type="integer", nullable=true)
*/
private $activationDate;
/**
* #var \int
*
* #Gedmo\Timestampable(on="create")
* #ORM\Column(name="deactivation_date", type="integer", nullable=true)
*/
private $deactivationDate;
but in the formtype class are those fields are setted as Datetime in order to show a date field to the user
->add('activation_date', DateTimeType::class, [
'label_attr' => [
'class' => 'font-weight-bold'
],
'required' => false,
])
->add('deactivation_date', DateTimeType::class, [
'label_attr' => [
'class' => 'font-weight-bold'
],
'required' => false,
])
and the fields are shown in the view this way
{{ form_start(form) }}
{{ form_row(form.title) }}
{{ form_row(form.description) }}
{{ form_row(form.activation_date) }}
{{ form_row(form.deactivation_date) }}
{{ form_row(form.active) }}
this code not work because the entity receives datetime and expects int values, how can I store unixtime values on the database but show datetime fields in the form for create and edit??
Set field option input to timestamp. Like this:
->add('activation_date', DateTimeType::class, [
'label_attr' => [
'class' => 'font-weight-bold'
],
'required' => false,
'input' => 'timestamp'
])
->add('deactivation_date', DateTimeType::class, [
'label_attr' => [
'class' => 'font-weight-bold'
],
'required' => false,
'input' => 'timestamp'
])
Related
I'm writing a form which contains all days of the week, but theses days are save in an int field $days. I'm using bitwise-op to display the selected days.
{% if (day.days b-and 1) == 1 %}
{{ "sunday" |trans }}
{% endif %}
{% if (day.days b-and 2) == 2 %}
{{ "monday" |trans }}
{% endif %}
....
I don't know how to do to display the checkbox array and convert it into an int and the opposite.
Here is a part of the formtype
$informations = $builder->create('information', FormType::class, [
'label'=>'Information',
'inherit_data' => true,
'label_attr' => ['class'=>'catlabel']])
->add('categoryQualityView', ChoiceType::class, [
'required' => true,
'label' => 'viewQuality',
'choices' => PlaceRepository::$categoriesRates,
'attr' => [
'class' => 'selectpicker',
],
])
->add('categoryGastronomy', ChoiceType::class, [
'label' => 'Gastronomy',
'required' => true,
'choices' => PlaceRepository::$categoriesGastronomy,
'attr' => [
'class' => 'selectpicker',
],
])
->add('price', MoneyType::class, [
'required' => false,
'label' => 'Price',
])
->add('days', IntegerType::class, [
'required' => false,
'label' => 'Days',
])
->add('description', TextType::class, [
'required' => false,
'label' => 'Description',
])
;
For your case you can create a custom "Form Field Type" (and maybe if needed a custom Data Transformer) and customize also the form template as described in the docs.
For example:
class DaysOfWeekType extends AbstractType
{
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'choices' => [
'Monday' => 1,
'Tuesday' => 2,
...
],
]);
}
public function getParent(): string
{
return ChoiceType::class;
}
}
i got an entity called "Recipes" that has a relation with another entity called "Ingredients".
/**
* #ORM\ManyToMany(targetEntity=Ingredients::class, inversedBy="recettes")
*/
private $ingredient;
What i need is to list all ingredients via my form builder, and it works well :
->add('ingredient', EntityType::class, [
// looks for choices from this entity
'class' => Ingredients::class,
'choice_label' => 'nom',
// used to render a select box, check boxes or radios
'multiple' => true,
'expanded' => true,
'label' => 'Ingrédients de la recette'
])
But i need to list them ordered by their name, so i've tried to add this line on my "Recipes ingredient field" :
* #OrderBy({"nom" = "ASC"})
But ingredients remains not ordered by their name.
Am i missing something ? :)
/**
* ...
* #ORM\OrderBy({"nom" = "ASC"})
*/
private $recettes;
or
->add('ingredient', EntityType::class, [
// looks for choices from this entity
'class' => Ingredients::class,
'choice_label' => 'nom',
// used to render a select box, check boxes or radios
'multiple' => true,
'expanded' => true,
'label' => 'Ingrédients de la recette',
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('u')->orderBy('u.nom', 'ASC');
},
])
I have a DateIntervalType field:
$builder
->add('effort', DateIntervalType::class, [
'label' => false,
'required' => false,
'widget' => 'integer',
'input' => 'dateinterval',
'with_years' => false,
'with_months' => false,
'with_days' => false,
'with_hours' => true,
'with_minutes' => true,
]);
If I submit the form I get the error message that it is invalid if I leave the hours and minutes empty. I have no constraints for the entity attribute (no #Assert\NotBlank() or anything like that) and it is nullable:
class Template
{
/**
* #ORM\Column(type="dateinterval", nullable=true)
*/
private $effort;
// ...
}
The submitted values are:
"effort" => [▼
"hours" => ""
"minutes" => ""
]
I want to submit the form without values and without getting this error.
You do not get errors if you change widget from integer to text:
$builder
->add('effort', DateIntervalType::class, [
// ...
'widget' => 'text',
// ...
]);
I have OneToMany related entities Gallery and Media stored in galleries_media
and I have Many To One related and Many To One related in GalleryMedia Entitiy
/**
* #var ArrayCollection
*
* #ORM\OneToMany(targetEntity="\Entity\GalleryMedia", mappedBy="gallery", cascade={"persist", "remove"})
*/
protected $galleriesMedia;
and in GalleryMedia Entitiy
/**
* #ORM\ManyToOne(targetEntity="\Entity\Gallery", inversedBy="galleriesMedia")
* #ORM\JoinColumn(name="gallery_id", referencedColumnName="id", nullable=false)
*/
protected $gllary;
/**
* #ORM\ManyToOne(targetEntity="\Entity\Media", inversedBy="galleries")
* #ORM\JoinColumn(name="media_id", referencedColumnName="id", nullable=false)
*/
protected $media;
how i do this in form
One-To-Many : sonata_type_collection
In your case:
class GalleryAdmin
{
// ...
$formMapper
->add('galleriesMedia', 'sonata_type_collection', [
'required' => false,
'label' => 'my_galleries_media_label',
'btn_add' => 'my_add_button_name',
'type_options' => [
'delete' => false,
],
], [
'edit' => 'inline', // or standard
'inline' => 'table', // or standard
'sortable' => 'id', // by any field in your entity
'limit' => 5, // you can remove this - this is a limit of items
'allow_delete' => false,
'placeholder' => $this->trans('admin.placeholder.no_media'),
])
;
class GalleriesMediaAdmin
{
// ...
$formMapper
->add('media', 'sonata_type_model_list', [
'required' => true,
'btn_add' => false,
'btn_list' => 'name_of_list_button'
'btn_delete' => false,
'btn_catalogue' => 'admin',
'label' => 'name_of_your_label',
], [
'placeholder' => 'choose media',
'edit' => 'inline',
'inline' => 'table',
'sortable' => 'id',
])
Many-To-Many : sonata_type_model
You can make many-to-many with doctrine:
class Gallery
{
// ...
/**
* Unidirectional Many-To-Many ()
*
* Every Gallery can have a lot of medias
*
* #ORM\ManyToMany(targetEntity="\Entity\Media")
* #ORM\JoinTable(
* name="gallery_media_table",
* joinColumns={#ORM\JoinColumn(name="gallery_id", referencedColumnName="id", onDelete="CASCADE")},
* inverseJoinColumns={#ORM\JoinColumn(name="media_id", referencedColumnName="id", onDelete="CASCADE")}
* )
*
* #Assert\Valid()
*/
protected $medias;
Then in your GalleryAdmin you should use sonata_type_model:
$formMapper
->add('medias', 'sonata_type_model', [
'multiple' => true,
'expanded' => true, // or false
'class' => Media::class,
'property' => 'name', // or any field in your media entity
'label' => 'your_label',
'btn_add' => true,
'btn_list' => false,
'btn_delete' => true,
'btn_catalogue' => 'admin', // or your own translate catalogue in my case file admin.en.yml
])
I have a problem with form collection on symfony.
I have 3 entities Article, AdditionnalFile, AdditionnalInformation
Article entity
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Category", inversedBy="articles")
* #ORM\JoinColumn(nullable=false)
* #Gedmo\Versioned
*/
private $category;
/**
* #ORM\OneToMany(targetEntity="AppBundle\Entity\AdditionnalInformation", mappedBy="article", cascade={"persist", "remove"})
* #ORM\JoinColumn(nullable=true)
*/
private $additionnalInformations;
/**
* #ORM\OneToMany(targetEntity="AppBundle\Entity\AdditionnalFile", mappedBy="article", cascade={"persist", "remove"})
* #ORM\JoinColumn(nullable=true)
*/
private $additionnalFiles;
AdditionnalInformation entity
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Article", inversedBy="additionnalInformations")
*/
private $article;
/**
* #ORM\ManyToMany(targetEntity="UserLdapBundle\Entity\Group", inversedBy="additionnalInformations")
* #ORM\JoinColumn(nullable=false)
*
* #Assert\Count(
* min = 1,
* max = 5,
* minMessage = "Il faut au minimum 1 groupe autorisé",
* maxMessage = "Il faut au maximum {{ limit }} groupe autorisé"
* )
*/
private $groups;
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="title", type="string", length=255)
* #Gedmo\Versioned
* #Assert\Type(type="string")
* #Assert\NotBlank()
*/
private $title;
/**
* #var string
*
* #ORM\Column(name="text", type="text")
* #Gedmo\Versioned
* #Assert\Type(type="string")
* #Assert\NotBlank()
*/
private $text;
I don't give the last entity because it's not important
I have create a form type for AdditionnalFile
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add(
'title',
TextType::class,
array(
'attr' => array(
'placeholder' => 'Titre'
),
'label' => 'Titre :'
)
)
->add(
'text',
TextareaType::class,
array(
'attr' => array(
'placeholder' => 'Texte'
),
'label' => 'Texte :'
)
)
->add(
'groups',
EntityType::class,
array(
'attr' => array(
'placeholder' => 'Droits'
),
'class' => 'UserLdapBundle:Group',
'choice_label' => 'name',
'expanded' => true,
'multiple' => true,
'label' => 'Accessible pour :'
)
);
}
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => AdditionnalInformation::class,
));
}
And I have create my article formtype who "embed" my additionnalInformationType
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add(
'title',
TextType::class,
array(
'attr' => array(
'placeholder' => 'Titre'
),
'label' => 'Titre :'
)
)
->add(
'category',
EntityType::class,
array(
'attr' => array(
'placeholder' => 'Catégorie'
),
'class' => 'AppBundle\Entity\Category',
'choice_value' => 'id',
'choice_label' => 'name',
'multiple' => false,
'label' => 'Catégorie :'
)
)
->add(
'text',
TextareaType::class,
array(
'attr' => array(
'placeholder' => 'Texte',
'class' => 'tinymce'
),
'label' => 'Texte :',
'required' => false
)
)
->add(
'tags',
TextType::class,
array(
'attr' => array(
'placeholder' => 'Tags'
),
'label' => 'Tags :'
)
)
->add(
'ticketNumber',
TextType::class,
array(
'attr' => array(
'placeholder' => 'Numéro de ticket, 301, 302,'
),
'label' => 'Numéro(s) de ticket :',
'required' => false
)
)
->add(
'groups',
EntityType::class,
array(
'attr' => array(
'placeholder' => 'Droits'
),
'class' => 'UserLdapBundle:Group',
'choice_label' => 'name',
'expanded' => true,
'multiple' => true,
'label' => 'Accessible pour :'
)
)
->add(
'additionnalInformations',
CollectionType::class,
array(
'entry_type' => AdditionnalInformationType::class,
'allow_add' => true,
'label' => 'Information(s) additionnel(s) :',
'prototype' => true
)
)
->add(
'additionnalFiles',
CollectionType::class,
array(
'entry_type' => AdditionnalFileType::class,
'allow_add' => true,
'label' => 'Fichier(s) :',
'prototype' => true
)
)
->add(
'save',
SubmitType::class,
array(
'label' => 'Sauvegarder',
'attr' => array(
'class' => 'btn-primary'
)
)
);
But now i have some question... :)
How can i custom the prototype? i want to use a bootstrap panel and put the additionnalInformation form inside.
And duplicate this for add other AdditionnalInformation
Is that possible ?
Here is a working example which I have used:
{% block _article_additionnalInformations_entry_row %}
<br>
<div class="panel panel-primary">
<div class="panel-heading">Information supplémentaire
<a href="#" class="btn btn-xs btn-danger pull-right">
<span class="glyphicon glyphicon-remove confirmation-suppression"></span>
</a>
</div>
<div class="panel-body">
<div class="row">
<div class="col-lg-8">
{{ form_row(form.title) }}
{{ form_row(form.text) }}
</div>
<div class="col-lg-4">
{{ form_row(form.groups) }}
</div>
</div>
</div>
</div>
{% endblock %}
You should try to write a custom twig theme. You can find more information on this page.
You can for example try to put this code in your template (where you render your form):
{% form_theme form _self %}
{% block _additionnalFiles_entry_widget %}
<tr>
<td>{{ form_widget(form.task) }}</td>
<td>{{ form_widget(form.dueDate) }}</td>
</tr>
{% endblock %}
Just make sure to use the right block name. You can do that by understanding how form fragment are named or just inspect a {{ dump(form) }} in your template.