I need to render a controller in a template (principal.html.twig) with #Route and #Template annotations in order to create a form:
{{ render(controller('PprsBundle:Default:SupuestoConfig'), {'strategy': 'inline'}) }
Controller:
/**
* #Route("/configsup", name="configsup")
* #Template("PprsBundle:Default:SupuestoConfig.html.twig")
*/
public function SupuestoConfigAction()
{
...
->add('number', 'text', array(
'constraints' => new Length(array(
'min' => 1,
'max' => 2,
)),
....
}
routing.yml:
configsup:
resource: "#PprsBundle/Controller"
type: annotation
SupuestoConfig.html.twig:
<form id="configurador" action="{{ path('configsup') }}" method="POST">
<p class="titulo_configurador">Elija supuesto penal:</p>
{{ form_row(form.tipo) }}
{{ form_row(form.numero, { 'label' : ' ', 'attr' : { 'class' : 'rec3' }}) }}
{{ form_rest(form) }}
<input id= "btTipoSupuesto" type="submit" value="Cargar" class="inputbt"/>
</form>
I'm having an unexpected behaviour when the constraint is activated (when I introduce a 4 digits number in "number" field) because it only renders the view SupuestoConfig.html.twig showing the constraint error (route /configsup) instead of the whole page (principal.html.twig). How can i make it work?
You are sending the form to the SupuestoConfigAction which renders only the form. You should send your form to the action where you render the form originally (where you use {{ render(controller('PprsBundle:Default:SupuestoConfig'), {'strategy': 'inline'}) }. Handle the form submission in that action and display the result.
So it's not a strange behaviour. It behaves exactly as you tell your program to.
Related
Suppose we have Symfony form type and a row adding field
$builder->add('name', 'text', ['attr' => ['class' => 'firstName', placeholder => 'first name']]);
I want this to be merged with attributes set in twig template:
{{ form_row(form.name, {'attr':{'class':'newClass'}}) }}
Currently it does replace. What is the best way to solve it?
You can use form variables to get form class attr, then concatene another class attr:
{{ form_row(form.name, {'attr':{'class':'newClass ' ~ form.name.vars.attr.class|default('')}}) }}
EDIT:
Corrected my previous answer after reading https://symfony.com/doc/current/reference/forms/twig_reference.html#reference-form-twig-variables
Trying to render a dropdown in Symfony 2.7.0 but I am having some issues when rendering the choices the view.
$form = $this->createFormBuilder(null)
->add('timespan', 'choice', array(
'choices' => array(90 => "3 months", 30 => "1 month")
))
->getForm();
...
return array(
'form' => $form->createView(),
);
...
Doing var_dump after this will display the values:
var_dump($form->get('timespan')->getConfig()->getOption('choices'));
But when rendering it in the view like this:
{{ form_widget(form.timespan, {'class': 'span2'}) }}
The select box becomes empty.
<select id="form_timespan" name="form[timespan]" required="required" class="span2"></select>
Any ideas why this might occur? Am I missing something?
The problem is obviously in Twig. You can debug this by editing the form theme, to see what values comes in and what is expected. The theme can be found at:
vendor/symfony/symfony/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig
(Or you can configure Symfony to use your own.)
You're looking for {% block choice_widget %} specifically to render this.
In this case it looks like you've forgotten to use the attr key for your HTML class:
{{ form_widget(form.timespan, {'attr': {'class': 'span2'}}) }}
You forgot the attr key in your call :
{{ form_widget(form.timespan, {'attr': {'class': 'span2'}}) }}
I have a many to many relationship between clients and assets.
For my edit client form I have multi-select box with which the user can select several assets to attach to a client. The form is using model-binding so it automatically populates the fields with the existing client data.
The model binding works for all fields in the form except the multi-select. Here is a snippet from my view:
{{ Form::model($client, ['route' => ['clients.update', $client->id], 'class' => '', 'method' => 'put']) }}
{{ Form::label('name', 'Name', $label_attributes) }}
{{ Form::text('name', null, array('class'=>'form-control')) }}
{{ Form::label('assets', 'Client Benchmarks (Select multiple)', $label_attributes) }}
{{ Form::select('assets[]', $assets, null, array('multiple' => true, 'class' => 'form-control')); }}
When I submit the form the relationship saves the data successfully via the sync method in my controller (update method):
$client = Client::find($id);
$client->name = Input::get('name');
$assets = Input::has('assets') ? Input::get('assets') : array();
$client->assets()->sync($assets);
$client->save();
Also, if I output the client assets directly they are accessible in the model collection in my form view:
<?php print_r($client->assets); ?>
How can I get the form to populate the select box with the existing selections?
echo Form::select('assets[]', $assets, array(1,2), array('multiple' => true));
As far as I know it won't set all selected values by default for you even when using form
model binding
This is what the native formBuilder method looks like:
public function select($name, $list = array(), $selected = null, $options = array())
I must be missing something really simple but I can't seem to find it. So I have my Resource defined in my routes.php but I need an additional route for an advanced search page with filters and stuff, my show/update/edit/create... pages are working perfectly but my search page isn't.
So in routes I have:
Route::resource('hostesses', 'HostessesController');
Route::get('/hostesses/search', 'HostessesController#search');
And I have a search form on my main page like this:
{{ Form::open(array('route' => 'hostesses.search', 'class' => 'navbar-form navbar-right')) }}
<div class="form-group">
{{ Form::text('search_term', '', array('class' => 'form-control')) }}
</div>
{{ Form::submit('Submit', array("class"=>'btn btn-default')) }}
{{ Form::close() }}
And when I use the search form I get the NotFoundHttpException
In my controller I have:
public function search()
{
return View::make('hostesses.search');
}
And I have created the template on views/hostesses/search.blade.php with a simple hello world message to check that it works, but I keep getting the exception!
Change the order of your routes and 'define' the named route of hostesses.search which is in your form
Route::any('/hostesses/search', array(['as' => 'hostesses.search', 'uses' => 'HostessesController#search');
Route::resource('hostesses', 'HostessesController');
Because what is happening is the resource for /hostesses/$id is capturing the search id, and returning an error that id of search does not exist
Also - change your route to Route::any(). This means it will respond to "get" and "post" requests.
However I would recommend splitting your route to be getSearch() and postSearch() functions and do this:
Route::get('/hostesses/search', array(['as' => 'hostesses.getsearch', 'uses' => 'HostessesController#getSearch');
Route::post('/hostesses/search', array(['as' => 'hostesses.postsearch', 'uses' => 'HostessesController#postSearch');
Route::resource('hostesses', 'HostessesController');
public function getSearch()
{
return View::make('hostesses.search');
}
public function postSearch()
{
// Do validation on form
// Get search results and display
}
And update your form
{{ Form::open(array('route' => 'hostesses.postsearch', 'class' => 'navbar-form navbar-right')) }}
You need to define a POST route:
Route::post('/hostesses/postSearch',array('as'=>'hostesses.search','uses' => 'HostessesController#postSearch'));
Then in your controller
public function postSearch()
{
var_dump(Input::get('search_term'));
}
I know that you can split a form out in twig and choose to not render the label for a particular field, but I can't help but think that you must be able to do this from the form class. The 'label' key in the options array lets you change this value to whatever you like, but passing either false or an empty string just returns the field name (see examples below where 'roles' is rendered as the label).
$builder
->add('roles', 'entity', array(
'class' => 'Acme\UserBundle\Entity\Role',
'label' => ''
));
$builder
->add('roles', 'entity', array(
'class' => 'Acme\UserBundle\Entity\Role',
'label' => false
));
Strangely, passing an empty space (which feels very dirty) seems to render a completely empty label, with no space even when viewing the source. Can anyone shed any light on the best approach, or even why the empty space seems to work?
Since Symfony 2.2 you can avoid the <label> rendering using the false value for the label attribute:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('Name', null, array('label' => false))
;
}
Source
Keep your 'View' specifications separate from your 'Model'
If you follow the accepted answer which says:
$builder
->add('Name', null, array('label' => false))
;
your form is not as re-usable. Especially if your form appears in more than one location (or might in the future).
If you do not want to render the form label it is best to do so in Twig (assuming your using Twig).
instead of rendering {{ form_row(form.name) }}, render each element separetly and exclude the form_label
ex.
{{ form_errors(form.name) }}
{# {{ form_label(form.name) }} <-- just dont include this #}
{{ form_widget(form.name) }}
If down the road you wanted the label in one instance of the form but the not the other, simply adding {{ form_label(form.name) }} would suffice; Where as changing array('label' => true) would turn the label on everywhere
If you are rendering your form with the one liner {{ form(form) }} then you should have a look at the symfony docs
Just add {'label':false} to your form_row()
{{ form_row(form.name, {'label':false}) }}
I don't understand very well your question but in form to show the name of label,personnaly I do like that :
$builder
->add('role', 'text')
in my twig :
<tr>
<td>{{ form_widget(form.role) }} </td>
<td>{{ form_label(form.role, "Name of Label") }}</td>
</tr>
<tr>
<td>{{ form_errors(form.role) }}</td>
</tr>
To hide my label, I had to render just the widget for the field, and not the label, e.g.
{{ form_widget(edit_form.event) }}
{{ form_rest(edit_form) }}
The problem with the ' ' label with a space in, is that it still renders the html input which is there and affects the page.
this should work (although its not a very clean solution)
$builder
->add('roles', 'entity', array(
'class' => 'Acme\UserBundle\Entity\Role',
'label' => ' '
));
(note the space between the ticks)