I create a form in controller:
$form = $this->createFormBuilder()
->add('test', TextType::class)
->add('submit', SubmitType::class)
->getForm();
and I have this code in my twig page:
{{ form(form, { 'attr': {'autocomplete': 'off'} }) }}
Now when I write a value for input (for example "123456") and when I submit the form and it's invalid, the page refreshes and my input value display "123456" and when I refresh page again value not change.
You have several ways to do it:
You can create a new form type and customise its rendering with a global form theme template
You can render the specific field differently
You can try to overwrite the value attribute while rendering the field (could not work on some form themes)
Read the symfony documentation on form themes to know which solution is better for your use-case or application.
Anyway, for a validation code input (as read in the comments) I suggest to you to implement a new form type entirely and handle its rendering, options and logic separately.
Related
I'm using submit form type in my FormType class (I want it to be customized for css classes and button label).
Since it's a search, I decided to go with GET, not default POST. What I noticed in Symfony2, is that:
submit field gets a "name" parameter
and when form is submitted, one of params in url is an empty "submit" (i.e.: http://url....?phrase=searchphrase&submit)
I tried to remove auto-genarated HTML "name" attr from the "button / submit" HTML tag in controller, in form type class, and even in Twig template, e.g. by overriding "name" - nothing seems to work for Symfony2, and the name="submit" for this button is always generated.
It there a way to remove this HTML attr from submit button, or am I forced to only render whole submit button by myself, and remove it from Form Type class?
Template for the search form is very basic, nothing extraordinary for Symfony2:
{{ form_start(form) }}
<div>
{{ form_widget(form.target) }}
</div>
<div>
{{ form_widget(form.phrase) }}
{{ form_widget(form.submit) }}
</div>
{{ form_errors(form) }}
{{ form_end(form) }}
And for the form type, I use standard submit:
$builder->add('submit', 'submit', array('label' => 'search', attr(name => null) ....)
As you see, here name attr is explicilty set to null. Symfony2 generate it any way, and give it a "submit" value to this 'name' attr.
The only problem is: can I make somehow Symfony2 to NOT generate "name" attr in the HTML Button/Submit tag? If Symfony2 cannot do that, it seems that the only way is to simply remove "submity" from Form Type class, and put HTML for this button directly in the template by myself, which I'm trying to not do (but if it's not possible, I will have to).
To me, it seems like it's a problem with Symfony2. Submit type is quite new thing in forms here, and I can imagine that auto-generated "name" attr follows the same rules as other form types in Symfony2 - although it is really not needed in HTML forms!
SOLUTION: So, I ended up with rendering it all by myself, and removed it from Form Type. Still I think Symfony2 shouldn't generate 'name' for this particular tag - I saw never ever "name" attr being assigned to SUBMIT button HTML tag in any form on the web, it's obviously not needed and not desired.
I think there are three solutions:
Have a form without the submit button and create the button outside of the form. Then submit the form with JS.
Override the default twig template responsible for generating HTML content of the submit button.
Generate the HTML content by yourself and not use the name there.
I need to add an attribute to a form field in symfony.
I do it like this in my form type:
->add('myfield','text',array('attr'=>array('myattrib'=>"test")))
But this overwrites defult attributes of that field (e.g. classes)
How can I add an attribute to a field without overwriting other attributes?
Thanks
you can add it using twig if you wanna just to keep your php code clear, here is an exemple :
{{ form_row(form.Address,{
'attr':{
'class':'form-control',
'min-length':'4',
'required':'true',
}
}) }}
In your form add the attribute like this :
->add('myfield','text',array('attr'=>array('myattrib'=>"test"),'mapped'=>false))
Otherwise you can add it in your twig view when rendering you form with form_row() just add the input like normale html and get int in your action after posting like this :
$posted_value = $this->get('request')->request->get('Name attribute of your input')
How can I render a single button defined through Symfony's Forms, using Twig?
Exactly how you render all the other form widgets e.g. if your submit button is configured like this:
$builder->add('submit', 'submit');
Then just render the "submit" form widget:
{{ form_widget(form.submit) }}
I have a form I need to use on multiple pages:
Controller
$emailForm = $this->get('form.factory')->createNamedBuilder('form', 'email_form')
->add('email', 'email')
->add('subject', 'text')
->add('body', 'textarea')
->getForm();
$request = $this->get('request');
if ($request->getMethod() == 'POST' && $request->request->has('email_form') ) {
$emailForm->bindRequest($request);
if ($emailForm->isValid()) {
// do stuff ...
$this->get('session')->setFlash('email_sent', "Woey, mail sent successfully!");
// Redirect on the same url to prevent double posts
return $this->redirect($this->generateUrl($this->getRequest()->attributes->get('_route')));
}
}
return $this->render('Bundle:Form:index.html.twig', array('email_form' => $emailForm->createView()));
Template
{% if app.session.getFlash('email_sent') %}
<p>{{ app.session.getFlash('email_sent') }}</p>
{% endif %}
<form action="{{ path(app.request.attributes.get('_route')) }}" method="post" {{ form_enctype(email_form) }}>
{{ form_widget(email_form) }}
<p><input type="submit" class="submit" value="Send" /></p>
</form>
It's really just standard Symfony2 form, almost like from tutorial.
I can't figure how can I efficiently use it on multiple pages (in multiple controller actions) without repeating myself (too much). So far I tried:
putting the logic into Base controller, which is parent for every controller where I want to have this form. There were 2 problems with this approach:
I couldn't figure how to redirect properly to the same page
I had to call method from parent in every action, which isn't really a problem, but I guess there has to be some more elegant way
rendering controller using embedded controllers in twig. However, I couldn't figure how to redirect properly.
So, what's the common approach to such forms?
Edit:
I'm looking for a no script solution.
I ended up using embedded controller on every page I needed, posting to different URL and saving cookie with referrer. Then I validate form, save cookie with results, redirect back to referrer and render results (errors, thank you message...). This seems to be the best option when you are dealing with scenarios where you have to think about disabled Javascript. You can easily disable creating of redundant cookies / flash sessions using simple conditions for cases when user is posting using AJAX.
The Symfony2 Forms tutorial addresses your scenario as well, see the Creating Form ClassesDocs Section in which "you'll learn how to build your form in a standalone class, which is recommended as your form becomes reusable" (Ibid.).
You should submit the data via an ajax post.
In the controller do your thing :p
Then render the form in the twig template, without extending layouts. (like it would be currently)
Then in any view you just replace the result: $('#formDiv').html(htmlReceivedBack);
I find it the easiest to just replace the whole html div again with the new rendered html; most likely you will show a success message or some form errors.
This way the user don't have to change pages just to send a message/feedback.
In a custom module, I have the following (to add javascript to a particular form):
function mymodule_form_mynode_node_form_alter(&$form, $form_state) {
drupal_add_js(drupal_get_path('module', 'mymodule') . '/js/mymodule.js', 'module');
}
This function does get called the form is first loaded (i.e. browse to http://myserver.com/node/add/mynode) however this php function does not get called when the same form is reloaded after the form has been invalidated (i.e. missed a required field after clicking 'Submit' or 'Preview').
What do I need to do to have the javascript file added after 'Submit' or 'Preview' is clicked?
Thanks,
John
To solve your problem, you'll need to create a theme function for the form where you render the form and add the js file.
You form alter is only called when the form is build. As forms are cached between request, the same and already build form is used on submit and preview.
You need to unsure that your code is called each time the form is rendered. As pointed out by googletorp, one way to do it is to use a custom form rendering function. You can also do it by attaching a post or pre-rendering function to your form. Actually, the custom, pre or post rendering function doesn't need to be for the form itself and can be used on any form element. Preferably the one which behavior is altered by the JavaScript.