I've created a page with tabs (using bootstrap), and all tabs have their own form. And they all work well. My problem is when I get a form error, I want to open the tab that the error is on.
My current controller code:
public function add(Request $request, EntityManagerInterface $em): Response {
$this->denyAccessUnlessGranted('ROLE_USER');
$entityAdd = new \App\Entity\add();
$form = $this->createForm(\App\Form\Add::class, $entityAdd);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
Function in AddFormType.php
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add(...)
->add(...)
->add(...)
->getForm()
;
}
I'm not creating the form myself, I'm using symfony form components but I'm not sure how to modify the form method to add the form hash (eg. /add#list-tab1) to the form method.
{{ form_start(AddForm) }}
{{ form_row(AddForm.name1) }}
{{ form_row(AddForm.name2) }}
{{ form_row(AddForm.save) }}
{{ form_end(AddForm) }}
You can pass the hash with the third parameter of createForm method :
$form = $this->createForm(
\App\Form\Add::class,
$entityAdd,
['action' => '#list-tab1']
);
Then, you can use the setAction() method and retrieve the option in the buildForm() method in your AddFormType.php file:
$builder
->setAction($options['action'])
->add(...)
Note: Using only the hash in the setAction() method (and not the full route), is only working if the form is submitted to the current route.
You'll have to replace #list-tab1 with the real tab id.
You can pass the action directly in the parameters of form_start(), in the Twig template:
{{ form_start(form, { action: '/add#list-tab1' }) }}
See the Symfony doc about this field option.
Related
want to display a form in a modal in the header. In order to make the form work I call the controller Homecontroller.
I called the controller with render controller in the branch but I got a blank page.
Thanks for your help.
header.html.Twig
<h1 class="fw-bold"></h1>
<p class="lead fw-bold"></p>
{{include ('fragments/modal_form.html.twig') }}
</main>
</div>
</div>
modal_form.html.twig
{{ render(controller(
'App\\Controller\\HomeController::index',{'form' : form.createForm()} )) }}
</div>
Controller :
* #Route("/", name="home")
*/
public function index(PostsRepository $postsRepository,TagRepository $tagRepository, Request $request ):Response
{
$listTag = $tagRepository->findAll();
$listPost = $postsRepository->findByPostPHp('php');
$posts = $postsRepository->findByExampleField($value = 6);
$partage = New Posts();
$form = $this->createForm(PartagePostType::class);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$partage = $form->getData();
$this->entityManager->persist($partage);
$this->entityManager->flush();
$this->addFlash('success', 'Votre post a bien été partagé');
}
return $this->render('home/index.html.twig', [
'posts' => $posts,
'tag' => $listTag,
'listPost' => $listPost,
'form' => $form->createView(),
]);
}
I dont' really get how you are trying to render you form but it doesn't work that way, in your modal_form.html.twig you should use the {{ form_start() }} and {{ form_end() }} twig helpers. They take in parameters the created view of the form, i.e, the variable "form" in your case (created in your render with the createView() method).
It should look like that:
{{ form_start(form}}
{{ form_row(form.field) }}
<input type="submit" value="submit">
{{ form_end(form) }}
"field" is whatever name you defined in your FormType. Notice how I added raw HTML for the submit button, it is suggested by Symfony you add the send button that way, even though you can add it in your FormType.
You can learn more about form rendering here : How to Customize Form Rendering
And forms in general there : Forms
Last thing, if you want to use multiple forms with this modal, don't forget to change the name of the variable (also don't forget to add this variable in your controller when you render a template with a form in it, obviously)
There Symfony project. He has Entity/Record.php With the command
php bin/console generate:doctrine:crud --entity=AppBundle:Record
Create a controller and a template. It seems to be nothing but one of the templates generated to create a new recording.
{{ form_start(form) }}
{{ form_widget(form) }}
<input type="submit" value="Create" />
{{ form_end(form) }}
Create a form in the controller
$record = new Record();
$form = $this->createForm('AppBundle\Form\RecordType', $record);
Create a form in Form/RecordType.php
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('surname')
->add('patronymic')
->add('dOB', BirthdayType::class)
->add('phone')
;
}
The form of work, all input fields are there, but the name in front of input fields, both logical and should have be generated - it attribute Entity object. But they are in English, which is inconvenient for the user (see. Screenshot). How do I display them in Russian?
In your RecordType add
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(
array(
'translation_domain' => 'forms'
)
);
}
and then create forms.ru.yml in app/Resources/translations/ clear cache so new translation file is detected (important) and you can write translations by
# forms.ru.yml
Name: Имя
Surname: Фамилия
Phone: Телефон
Above I assume your locale is set to ru if it's not then you will need to adjust file name.
I often need to render very simple imputs in some of my templates.
I'd like to take advantage of the twig macros & form blocks to render certain HTML inputs without involving the whole Symfony forms machinery.
For example from the controller:
$templateContext = array(
'my_input' = new FormField('my_input', 'choice', array(
'choices' => array('value1', 'value2', 'my_value'),
'value' => 'my_value',
));
);
In the template:
<div>{{ form_widget(my_input) }}</div>
would render:
<div>
<select name="my_input">
<option>value1</option>
<option>value2</option>
<option selected="selected">my_value</option>
</select>
</div>
Is there a simple way to do that ?
Eventually I would also like to be able to reuse these fields elsewhere (like we can reuse form types)
There are many ways to go about this. The easiest would be to write the plain HTML into your twig template.
<form method="post">
<div>
<select name="my_input">
<option>value1</option>
<option>value2</option>
<option selected="selected">my_value</option>
</select>
</div>
</form>
And then in your controller read the values back.
$request = $this->getRequest();
if($request->getMethod() == 'POST'){
$data = $request->get('my_input')
//Do whatever you want with $data
}
If you want you re-use the html, you can build it somewhere in your PHP and pass it into Twig whenever you need it; or you can place it in a separate twig template and read that with the {include ''} command in twig.
Here is what I finally ended up with:
Class MyInput {
public static values = array(
'value1',
'value2',
'my_value',
);
}
class MyInputType extends AbstractType
{
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'choices' => MyInput::$value,
));
}
public function getParent() { return 'choice'; }
public function getName() { return 'my_input_type'; }
}
Field type used from the controller (after having registered it as a service)
public function MyAction(Request $request)
{
$form = $this->createForm('my_input_type');
$form->handleRequest($request);
$templateContext['myForm'] = $form->createView();
// ...
}
Input rendered into the template
<div>{{ form(myForm) }}</div>
To conclude: I've not been able to render an input without the form machinery, but the actual form remains rather simple.
I found my own solution for it since i need to create subforms from existing forms.
create totally empty twig template,
add in it only {{form(form)}}
render this template render()->getContent()
do a preg replace on the result (i do it in js) formView = formView.replace(/<(.*?)form(.*?)>/, '');
Yes yes - i know that regex is not perfect so before someone says it - i say it on my own, change it for youself as it catches "form-group" classes etc as well.
This is just a showcase of my solution
I have been trying to setup a hidden custom field type and a transformer like in this example: https://gist.github.com/bjo3rnf/4061232
What I am trying to accomplish is to pass an entity trough a hidden element, that entity should map the form´s entity but for some reason when it get to the controller it get empty.
Can some one help me on how can I pass an entity trough a form?
Thank you
The solution with the custom type and transformer is probably better, but if you just want a quick hack, you can set your field up as an entity type in the formbuilder
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('yourField', 'entity', array('class' => 'AppBundle\Entity\YourEntity', 'read_only' => true));
}
and then do something like this in your template:
<input type="hidden" id="{{ form.yourField.vars.id }}"
name="{{ form.yourField.vars.full_name }}"
value="{{ form.yourField.vars.value }}" />
{% do form.yourField.setRendered %}
Note that this has to be at the top of your form, before you invoke form_widget()
I want view 20 same fields (name: matchday) with use "prototype".
I have a code like this:
Form:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('matchday', 'collection', array(
'allow_add' => true,
'type' => new MatchdayType(),
))
...
}
and View (Twig):
<form action="{{ path('meet_create') }}" method="post" {{ form_enctype(form) }}>
{% for i in 1..20 %}
{{ form_widget(form.matchday.vars.prototype) }}
{% endfor %}
<p>
<button type="submit">Create</button>
</p>
</form>
but I don' know how use iteration in this code with "prototype" .
thanks
The prototype is only a model that you can use to create new fields in the form's collection, but it's not really a field per say. If you want to display 20 empty fields from the beginning, you have basically two choices:
add 20 empty 'matchday' objects in the form object in your controller before creating the form
use Javascript (jQuery) to add the fields in the view on the client side
The first solution would give something like this:
$meet = new Meet();
for ($i=0; $i < 20; $i++) {
$matchday = new MatchDay();
$meet->getMatchdays->add($matchday);
}
$form = $this->createForm(new MeetType(), $meet);
For the second solution, you have a good example in the Symfony Cookbook about form collection: http://symfony.com/doc/current/cookbook/form/form_collections.html