Easyadmin 3 - How to render embedded form? - php

I am trying EasyAdmin, and I am completely lost.
I have entity A which contains a relationship with entity B (which contains multiple fields).
In Entity A's CrudController, if I want to display fields from the relation (so, Entity B), how am I supposed to go about it?
In my current case I have a Portfolio entity that has a relationship with UserDetails (and which contains several fields that I therefore want to display in the form of the Portfolio entity)
I created a FormType for my UserDetails class, as we normally would. And in my CRUD controller, for the Portfolio entity, I put this:
public function configureFields(string $pageName): iterable
{
return [
IdField::new('id'),
FormField::addPanel()->setProperty('userDetails')->setFormType(ProjectUserDetailsType::class)
];
}
Is this the right way to go? Will the fields contained in this FormField be mapped correctly?
On the other hand when rendering, this "subform" is centered, unlike the others.

When you try to embed a single object or form you could follow this doc
If you want also embed a collection of objects there is a way for that using what is called prototypes.
For rendering the form and styles you could render each part separately and adding the proper styles on twig files or inside the form definition.
#rendering with twig
{{ form_label(form.field, 'label', { 'attr': {'class': 'foo'} }) }}
{{ form_widget(form.field, { 'attr': {'class': 'bar'} }) }}
#rendering inside html tags
<div class="form-control">
<i class="fa fa-calendar"></i> {{ form_label(form.dueDate) }}
{{ form_widget(form.dueDate) }}
<small>{{ form_help(form.dueDate) }}</small>
<div class="form-error">
{{ form_errors(form.dueDate) }}
</div>

Related

How can I use a twig variable as a form field name

I have a form template which has a repeated block for several similar form fields. It is used as follows:
{# form_template.html.twig #}
{{ include ('company-select.html.twig', {field: 'companiesInclude'})
{{ include ('company-select.html.twig', {field: 'companiesExclude'})
{{ include ('company-select.html.twig', {field: 'companiesLinked'})
Now I have a company select template, which looks as follows:
{# company-select.html.twig (simplified, the actual template is much more complex) #}
<div class="form form-field selector" id="{{ field }}">
{{ form_label(form.field) }}
{{ form_widget(form.field) }}
</div>
The way it is, the template fails, because 'field' is not a property of the FormView class.
How can I make the template interpolate the twig variable into the form_xxx function call as an actual field name?
A property of an object or an array element in twig can either be accessed via the dot notation (.) or via the square bracket one ([]).
If your property happens to be a twig variable, you will need to use the later form.
So in your case:
form_label(form[field])
form_widget(form[field])
Your code in company-select.html.twig ending up being:
<div class="form form-field selector" id="{{ field }}">
{{ form_label(form[field]) }}
{{ form_widget(form[field]) }}
</div>
This is, in a really simplified example, testable here.
Note that, in a more complex flavour, you can also use the attribute function
., []: Gets an attribute of a variable.
Source: https://twig.symfony.com/doc/3.x/templates.html#other-operators
Also worth reading on the same note: https://twig.symfony.com/doc/3.x/templates.html#variables

How to autorewrite input labels for the form in Ttwig?

I use almost standard CRUD form rendering in Twig:
{{ form_start(form, {'attr' : {'class' : 'new_edit_form'}}) }}
{{ form_widget(form) }}
<input type="submit" value="{{ 'default.new.create'|trans }}"/>
{{ form_end(form) }}
In this case all inputs have labels with upper case property names:
Title
Description
Date
I have translations enabled in my project and Twig tries to translate these words, but in my dictionaries all properties have ids like field.property_name.
So I want to go through all form inputs and rewrite all labels making them lower case and adding 'field.' prefix. How can I do this in cycle?
Symfony 3.4
In order to overwrite the translations you need to add the messages.en.yml to the app/YourBundle/Resources/translations and overwrite the messages you want like:
field.property_name: Your label here
This can help: How to translate labels in symfony2 forms with messages.en.yml?
You can define a specific label for each field:
$builder->add('save', TextType::class, array(
'label' => 'field.sth'
))

form_widget with dynamic form name

In my Twig template I have a FOR LOOP that creates a multiple number of forms like so:
{% for thing in things %}
{% set form_id = 'myform_' ~ thing.Id %}
{% set form_name = attribute(form, 'myform_' ~ thing.Id) %}
{{ form_widget(form_id) }}
{{ form_widget(form_name) }}
{% endfor %}
I would like this to generate the following:
{{ form_widget(myform_1) }}
{{ form_widget(myform_2) }}
.... and so on.
I left my 2 failed attempts in there, (form_id and form_name), to save anyone from suggesting those as possible solutions.
To summarize; I need to insert the dynamically created value (myform_1, myform_2) inside of {{ form_widget() }}
You can render dynamic fields form with dynamic name in Twig with special function of Twig :
{{ attribute(object, method) }}
{{ attribute(object, method, arguments) }}
{{ attribute(array, item) }}
With this function you can easily generate dynamic string name for your field dynamic into your form like this
{{ form_widget(attribute(form, 'myfielddynamicname' ~ var ~ ' lastchar')) }}
With this variable "var" (array or others type) you can render lot of dynamic form name like :
myfielddynamicnamefoolastchar
myfielddynamicnamebarlastchar
myfielddynamicnameneolastchar
For more understanding you can read this official twig documentation function
here : attribute twig function documentation
The things myform_1 and myform_2 simply are variables with FormView object as you define in your controller.
I don't know if Twig allows on dynamic variables call, although you can collect these form objects in array in controller before passing to view. After this step, you can just iterate thought this array It will manage the problem you are facing with.
Don't create a loop in your Twig: the layout should only render a single form. Then you can build the forms in your controller and render each one of them.
See this documentation on the Symfony book on how to get the result of a rendered template. You can concatenate the single render results and return a response with the full content.

Symfony2/Twig - Add classes to form elements

I've just started a new Symfony2 project where I've used the generate:doctrine:crud to quickly scale out a few views, forms, etc.
The generated form code is just:
{{ form(form) }} but includes a generic create or delete button. I was wondering how I could add a class to these generic buttons or modify them in any way since it's just encompassed in {{ form(form) }}?
For reference I'm using Twitter Bootstrap to quickly apply some styles so I don't want to change the css based on the submit button.
Thanks!
You can specify CSS classes in the form builder class to avoid filling your Twig template with html even for rendering the form individually.
When you call {{ form(form) }} you are using a helper to simplify your code so you don't have to call form_widget for each one of your fields, but doing so you can't control the exact display in the template. To do it you have to specify the class that will be applied to the field.
In the WhateverType.php file, inside the Forms folder, you have the form builder. There you should have something like:
$builder
->add('text')
->add('whatever')
There you have to add the classes:
$builder
->add('text', 'attr'=> array('class'=>'btn')
->add('whatever')
Then, when your form is displayed in the template, it will apply the classes that you specified in the builder.
After following dmnptr's answer (breaking form into parts), you can pass an array of arguments to each form / form_row / form_label etc by:
{{ form(form, { 'attr': { 'class': 'your-css-class-1 your-css-class-2' } } ) }}
The attr param sets attributes for the item, so the above would produce:
<form class="your-css-class-1 your-css-class-2" ...
You are going to have to render each filed by hand and add necessary classes to elements in your TWIG. Read on how to do it in the official docs - http://symfony.com/doc/current/book/forms.html#rendering-each-field-by-hand

Symfony2 embedded form - get entity field

I have an entity with a many-to-many association.
What I'm trying to do is:
create the form for the main entity
embed the associated entities
I have been able to do both the points above, but now I cannot figure out how to retrieve an associated entity field.
My classes are Gallery and Immagine. Immagine has 3 properties, image, imageName and file.
Inside my GalleryType buildForm function I do this:
->add('immagini', 'entity', array(
'class' => 'MySiteBundle:Immagine',
'property' => 'image',
'multiple' => true,
'expanded' => true
))
Now, in my edit.html.twig template, if I write this
{% for img in edit_form.immagini %}
<li>
{{ form_widget(img, {'attr': {'style': 'vertical-align: top'}} ) }}
{{ form_label(img, null, { 'label_attr': {'style': 'display: inline'}} ) }}
</li>
{% endfor %}
...and the result of embedded images inside a gallery edit page, is correct and works great.
Now, what I want to do is to display in the same li tag, another Immagine field, let's say imageName.
I've tryed so many ways, but I'm not able to do it...
Any suggestion?
You should embed your associated entity by using collection type, not entity type like you did.
->add('immagini','collection',array('type'=>new ImageType(),'multiple'=>...,))
So, you need to implement a new form class, call it what you like eg. ImageType(). In that class type add whatever form types(properties) you would need to display, eg.
->add('imageName','text')
->add(...
Than you would be able to iterate and display it from twig code.
Take a look at basic form embedding docs:
http://symfony.com/doc/current/cookbook/form/form_collections.html

Categories