Symfony2.1: how to render a "repeated" widget by hand - forms

In Symfony2.1 (as well in Symfony2.0) one can render a widget by hand in a Twig template. So, if one would to render a text field name "username", the related label, error and input can be rendered separately, i.e.:
{{ form_label(form.username) }}
{{ form_errors(form.username) }}
{{ form_widget(form.username) }}
In Symfony2.1, the Repeated field group has been introduced. It is useful to ensure the user is not inserting a wrong value for an important entry (e.g. the email or password).
The question is, how to render it in a Twig template by hand?
Please, notice that {{ form_widget(form.username) }} in this case will render the whole component (i.e. both labels and inputs).

$builder->add('userPass', 'repeated', array(
'type' => 'password',
'label' => 'Zayso Password',
'required' => true,
'invalid_message' => 'The password fields must match.',
'constraints' => new NotBlank(),
'first_options' => array('label' => 'Zayso Password'),
'second_options' => array('label' => 'Zayso Password(repeat)'),
'first_name' => 'pass1', // form.userPass.pass1
'second_name' => 'pass2', // form.userPass.pass2
));
In your template you can do: {{ form_widget(form.userPass.pass1 }}. Not sure where it is documented but found it somewhere.

Late answer, but you can also add
{{ form_widget(form.username.first) }}
to generate the first widget element.
If you want to display the label and widget separately, you can use:
{{ form_label(form.username.first) }}
{{ form_errors(form.username.first) }}
{{ form_widget(form.username.first) }}
{{ form_label(form.username.second) }}
{{ form_errors(form.username.second) }}
{{ form_widget(form.username.second) }}
Here is the documentation for Repeated Field Type.

Related

Laravel Blade Form::checkbox rendered as select

I have a form that should display as checkboxes but is appearing as a select dropdown.
In the controller I defined the variables:
$user = Auth()->user();
$users = User::all();
$assignedUsers = User::where('assigned', true)->get();
Here is where the form is defined in the view:
{{ Form::open( route('users.access', [$user->id]), ['type' => 'PUT']) }}
{{ Form::checkbox(
'Users',
[
'label' => __('Select Users'),
'options' => $users,
'value' => $assignedUsers
]
) }}
{{ Form::button('submit', ['label' => __('Save changes')]) }}
{{ Form::close() }}
The form is rendering but not as checkboxes but a select dropdown. What am I missing here?
Form::checkbox() method accepts 3 arguments, name, value, and default. You seem passing wrong arguments for the checkbox list so it renders as dropdown, to make a checkbox list, you and use a loop, should be something like so:
#foreach ($users as $user)
<label>
{{ Form::checkbox('users[]', $user->id, isset($assignedUsers[$user->id])) }}
{{ $user->name }}
</label>
#endforeach
Note that I have converted your $assignedUsers variable to key by id for more convernience. You can use your own check method.
$assignedUsers = User::where('assigned', true)->get()->keyBy('id');

How to add an error to a constraint in form?

Using Symfony 3.2 on Ubuntu 16.04
I created a FormType.php with several fields. One of them is a phone number, so I added a constraint where only numbers could be accepted. Here is the code for the phone form
->add('authorPhone', NumberType::class, array('label' => 'Numéro de téléphone',
'required' => true,
'attr' => array(
'class' => 'validate',
'id' => 'icon_telephone'
),
'constraints' => array(new Regex("#^0[1-9]([-. ]?[0-9]{2}){4}$#"))
))
After that, in my controller I added an error to tell that numbers only need to be filled in
public function indexAction()
{
$form = $this->createForm(FormType::class);
$form->get('authorPhone')->addError(new FormError('error message'));
return $this->render('app/main/index.html.twig', array(
'form' => $form->createView()
));
}
But when I look at my page the error message is actually showing without having filled the field. And of course I don't want that.
(you can see under "Numéro de téléphone", which means phone number)
I only want numbers in my phone number field, and if there are letters, an error should be displayed or something saying it's not right.
Standard how to to this stuff in Symfony is to define an entity with contraints and error messages and then create entity bound form which will handle validation based on entity's contraints automatically.
But if you need, for some reason, independent form, it can be done to. The addError() method is for adding error "state" the the form field (e.g. for own validation) and you're adding the error by default right after the form is created. That's the reason why the error shows constantly.
UPDATED:
The right way to assign an error message to a form field is by the invalid_message property (which is showed when the entered value doesn't correspond with the field type). But when there's a constraint used for validation, then the err message has to be set according to the constraint validator - so, in your case, by associative array with pattern and message keys.
Next thing need to be corrected is TextType instead of NumberType, because when the NumberType is used, then it won't allow to enter dashes and also automatically trims leading zeros in numbers - so bad for phone numbers :-)
->add('authorPhone', TextType::class, array(
'label' => 'Numéro de téléphone',
'required' => true,
'attr' => array(
'class' => 'validate',
'id' => 'icon_telephone'
),
'constraints' => array(new Regex(
array(
'pattern' => '#^0[1-9]([-. ]?[0-9]{2}){4}$#',
'message' => 'Phone error message'
)
)),
))
And last thing to review - in the controller (after form declaration) has to be form submission handling routine:
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
....
You can learn more in Symfony's form submission handling: http://symfony.com/doc/current/forms.html#handling-form-submissions
Form rendering is fairly simple. Twig syntax to render whole form:
{{ form_start(form) }}
{{ form_widget(form) }}
{{ form_end(form) }}
or, if you want to selectively render fields one by one:
{{ form_start(form) }}
{{ form_row(form.authorPhone) }}
{{ form_row(form.submit) }}
{{ form_end(form) }}
It'll renders complete field including labels and errors

Symfony form builder only works when fields are in a given order

Here is a working code:
$formBuilder = $this->get('form.factory')->createBuilder('form', $scene);
$formBuilder->add('text', 'textarea', array('required' => false));
$formBuilder->add('duration', 'time', array('with_seconds' => true, 'input' => 'string'));
$formBuilder->add('submit', 'submit');
$form = $formBuilder->getForm();
$form->handleRequest($request);
When I switch the lines like this:
$formBuilder = $this->get('form.factory')->createBuilder('form', $scene);
$formBuilder->add('duration', 'time', array('with_seconds' => true, 'input' => 'string'));
$formBuilder->add('text', 'textarea', array('required' => false));
$formBuilder->add('submit', 'submit');
$form = $formBuilder->getForm();
$form->handleRequest($request);
it doesn't work anymore: the value of duration becomes 0 instead of something in the form of 00:00:00.
I have no template to display them. In my twig page, I simple use {{ form(form) }}.
What's going on, there?
I copied your code and find anything wrong with it, you should be able to change the order of lines. But indirect solution would be leaving your code from the first example and manipulate order in the twig template:
{{ form_errors(form) }}
{{ form_row(form.duration) }}
{{ form_row(form.text) }}
{{ form_rest(form) }}

bootstrap style conflicts with forms bound with models laravel 4

I am developing an application with laravel 4, I have forms that are filled with data from a model, in other words a model is bound to the form
I need to add some bootstrap style to the form and I do it this way
this is my view file:
{{
Form::model($user, array( $user->id))
}}
{{ Form::label('last_name', 'Last Name') }}
{{ Form::text('last_name', '', array('class' => 'form-control')) }}
{{ Form::close() }}
and this is my controller code:
public function edit(){
$user = User::find(Auth::user()->id);
return View::make('edit')->with('user',$user);
}
The Issue:
As soon as I add this class to the form's element the content of the form will disappear and no data is bound to it anymore, how should I fix it?
I found the answer the second argument of this
{{ Form::text('last_name', '', array('class' => 'form-control')) }}
is the input value of text field so it should be like this:
{{ Form::text('last_name', $user->last_name, array('class' => 'form-control')) }}

Symfony2 Accessing each entity field elements value in Twig

I have one form that contains entity type field parameters:
->add('parameters', 'entity', array(
'class' => 'SPlaceBundle:Parameter',
'query_builder' => function(ParameterRepository $er)
{
return $er
->createQueryBuilder('s')
->where('s.type = :type1 or s.type = :type2')
->setParameter('type1', 1)
->setParameter('type2', 2)
->orderBy('s.name', 'ASC');
},
'property' => 'name',
'multiple' => true,
'expanded' => true,
))
As you can see I only display parameters with type=1 or type=2.
While rendering template I would like to place hr (or something else) between checkboxes representing different parameter types.
I was trying to use {{ field.get('value').type }} trick to get parameter type:
{% for p in form.parameters %}
{{ form_widget(p) }}
{{ form_label(p) }}
{{ p.get('value').type }}
<br>
{% endfor %}
The problem is that above {{ p.get('value') }} returns parameter id (int) instead of parameter object.
Is there a way to return object?
It's not really elegant, but you could concatenate the type and name in your select, and use that as label. Then, when displaying the labels, split on the delimiter and you have both type and name.