Display input field based on item selected in list - symfony

I'm using Symfony to make a website for a tennis club, and I'm beating my head down about something :
I want to display an input field based on the option selected in a dropdown list.
This is the scenario :
I'm the admin of the website, and I want to make a reservation. If the reservation is a tournament (selected from a ChoiceType list), I want to display an input field to enter the tournament name.
I want to do something that would look like this in my twig view :
<div class="form-group">
<div class="col-xs-4">
{{ form_label(form.reservationType) }}
{{ form_widget(form.reservationType, {'attr': {'class': 'form-control' }}) }}
</div>
</div>
{% if reservationType == "tournament" %}
<div class="form-group">
<div class="col-xs-4>
{{ form_label(form.tournamentName) }}
{{ form_widget(form.tournamentName) }}
</div>
</div>
{% endif %}
Is it possible to do that just with twig ?
Thanks in advance!

You must use jQuery to solve this issue :
$(document).ready(function(){
$('.reservation').change(
var reservation = $(this).val();
if (reservation == 'xxxx'){
$('.tourName').show();
}else{
$('.tourName').hide();
}
);
});
<div class="form-group">
<div class="col-xs-4">
{{ form_label(form.reservationType) }}
{{ form_widget(form.reservationType, {'attr': {'class': 'form-control reservation' }}) }}
</div>
</div>
<div class="form-group">
<div class="col-xs-4>
{{ form_label(form.tournamentName) }}
{{ form_widget(form.tournamentName, {'attr': {'class': 'hidden tourName' }}) }}
</div>
</div>

No it is not possible only with twig.
What you can do is add a script to your template:
<div class="form-group">
<div class="col-xs-4">
{{ form_label(form.reservationType) }}
{{ form_widget(form.reservationType, {'attr': {'class': 'form-control reservation-type' }}) }}
</div>
</div>
<script type="text/javascript" src="{{ asset('bundles/yourBundle/theNameOfTheScriptYouPutInRessourcesPublic.js') }}"></script>
Then in the script (with jquery) you just listen to change event on the select to insert the input.
$('select.reservation-type').change(function(
if($(this).val() == 'tournament')
{
$('<input type="text" />').appendTo($(this).parent('form-group'));
}
));
If your inputs need twig variables or something you can add the inputs as hidden in the twig template and then in the script you just change the type from hidden to text or whatever you need:
$('select.reservation-type').change(function(
if($(this).val() == 'tournament')
{
$('input[name="tournament-name"]').prop('type', 'text');
}
));
If you don't want to use javascript you could consider using a form event listener: http://symfony.com/doc/current/form/dynamic_form_modification.html

Related

How to make RadioButton in Symfony Form?

I have form that i have to redo with Symfony Form but i stuck on this place:
<div class="currency-label">
<input checked id="cur1" name="currency" type="radio">
<label for="cur1">EURO</label>
</div>
<div class="currency-label active">
<input id="cur2" name="currency" type="radio">
<label for="cur2">USD</label>
</div>
This is how it looks:
how to make radiobutton with Symfony Forms?
In my form class i added:
->add('vacancyCurrency', RadioType::class, ['required' => false])
and to my template
{{ form_widget(form.vacancyCurrency) }}
my form became shorter and obviously no css :
and if i add css class to form it looks differently :
{{ form_widget(form.vacancyCurrency, {'attr':
{'class': 'currency-label'}
}) }}
The best way to do it is to render a ChoiceType as radio buttons:
->add(
'vacancyCurrency',
ChoiceType::class,
[
'choices' => [
'US Dolar' => 'usd',
'Euro' => 'eur',
],
'expanded' => true
]
);
The ChoiceType field it's rendered as radio buttons when you have the options multiple = false and expanded = true. The option multiple is not in the code above because its default value is false. You can find more details here
Edit:
In your twig template, you just need to add:
{{ form_widget(form.vacancyCurrency) }}
Edit 2
You said in the comments to this answer that you need to put each radio button inside a <div class="currency-label active">. I believe you can't do it by setting attributes in the Symfony Form Field itself. The options you have there, like choice_attr operate in the input, not in the divs that surround it.
It's possible to achieve what you want, but you'll need to write some code and render the radio buttons by hand, like:
<div class="form-group">
<label class="control-label required">Vacancy currency</label>
{% for child in form.vacancyCurrency %}
<div class="currency-label active">
<label for="{{ child.vars.id }}" class="required">
<input type="radio" id="{{ child.vars.id }}" name="{{ form.vars.id ~ '[' ~ form.vacancyCurrency.vars.name ~ ']' }}" required="required" class="checkbox" value="{{ child.vars.label }}">
{{ child.vars.label }}
</label>
</div>
{% endfor %}
</div>
Of course, you can use some Javascript to do the job. For example, you can render the form field like:
{{ form_widget(form.vacancyCurrency) }}
It will add each radio button inside a div with class="radio".
Then you can change the class to what you want as soon as the page is ready with some JQuery:
$(document).ready(function() {
$(".radio").attr("class", "currency-label active");
});
So that is how i solved this, in template:
{{ form_start(form) }}
{% form_theme form _self %}
{% block choice_widget %}
{% for child in form.vacancyCurrency %}
<div class="currency-label">
{{- form_widget(child) -}}
{{- form_label(child, null) -}}
</div>
{% endfor %}
{% endblock choice_widget %}
{{ form_end(form) }}
in form class:
->add('vacancyCurrency', ChoiceType::class, [
'choices' => [
'USD' => 'USD',
'RUB' => 'RUB',
],
'expanded' => true,
])
and to make one of them active i set default data in model:
public $vacancyCurrency = 'RUB';
Update
now i have interface for currency and use it in form class:
->add('currency', ChoiceType::class, [
'label' => 'Валюта',
'choices' => \array_combine(CurrencyInterface::ALL, CurrencyInterface::ALL)
])

TimeType styling

I am trying to style my input field in Symfony 3.4 with symfony forms for some duration(hours and minutes only). I am trying with clockpicker but I don't know where I am wrong. If someone can help me or there is a better solution. I have downloaded and included my js and css in web folder.
I am trying to make it like this in the moment:
My twig:
<div class="form-group col-md-4">
<label for="time_for_cooking">Време за готвене(минути):</label>
{% if form_errors(form.recipeCookingTime) %}
{{ form_widget(form.recipeCookingTime, { 'attr': {'class': 'form- control clockpicker-control clockpicker is-invalid'} }) }}
<div class="col">
<small class="text-danger">
{{ form_errors(form.recipeCookingTime) }}
</small>
</div>
{% else %}
{{ form_widget(form.recipeCookingTime, { 'attr': {'class': 'form control clockpicker-control clockpicker'} }) }}
{% endif %}
</div>
My RecipeType.php
->add('recipeCookingTime', TimeType::class)
document ready
<script>
$(document).ready(function() {
('.clockpicker').clockpicker();
} );
</script>
and what its generated, I think the problem is these selects that being genereted
In your FormType you have to set the html5-attribute to false to get an input.
See here https://symfony.com/doc/current/reference/forms/types/time.html#html5

Symfony 2 collection of forms - prototype

I would like to use prototype like here http://symfony.com/doc/current/cookbook/form/form_collections.html#allowing-new-tags-with-the-prototype, but my form looks:
<div class="form-group row">
<div class="col-md-4">{{ form_widget(productAttribute.attribute, {'attr': {'class': 'form-control'}}) }}</div>
<div class="col-md-6">{{ form_widget(productAttribute.value, {'attr': {'class': 'form-control'}}) }}</div>
</div>
Before the loop is a div with data-prototype attribute which contains form fields without wrapped divs and classes and I don't know how to get wrapped divs with classes there. Thank you for your advice.
Twig side:
<div id="template" style="display: none">
{{ form_widget(form.tags.vars.prototype)|e }}
</div>
Js side:
var templateContent = $.("#template").html();
Or, twig:
{% set subform = form.tags.vars.prototype %}
{{ form_row(subform.fielName) }}
...

How to show validation error message in front of each field in symfony2

I'm new to symfony and twig. I want to build my html forms using BootStrap CSS Framework. So my form looks like this in twig file:
<form action="{{ path('register')}}" class="form-horizontal span10 offset7" id="frmRegistration" method="POST" {{ form_enctype(form) }} novalidate>
<fieldset>
{{ form_widget(form._token) }}
<div class="control-group">
{{ form_label(form.userName, null, {'label_attr': {'class':'control-label'}})}}
<div class="controls">
{{ form_widget(form.userName, {'attr': {'data-path': path('ajax_user_exists') } }) }}
</div>
</div>
<div class="control-group">
{{ form_label(form.password.first, null, {'label_attr': {'class':'control-label'}})}}
<div class="controls">
{{ form_widget(form.password.first) }}
</div>
</div>
<div class="control-group">
{{ form_label(form.password.second, null, {'label_attr': {'class':'control-label'}})}}
<div class="controls">
{{ form_widget(form.password.second) }}
</div>
</div>
<div class="control-group">
<div class="controls">
<input id="register_submit" type="submit" value="تاييد" class="btn btn-primary" />
</div>
</div>
</fieldset>
Now I want to show validation error messages exactly in front of each input. My problem is that how can I do this using twig? If I use {{ form_row(form.firstName) }} it will generate the label and input. But I cant wrap them inside the Bootstrap form structure. Any help is appreciated in advance.
UPDATE
Sorry for not being precise when reading symfony documentation. I found the solution. Using {{ form_errors(form.firstName) }} solved the problem.
This is still showing up as unanswered and thought it would be helpful if the answer was added at the end so this could be closed.
To add an error message on a form row, use:
{{ form_errors(form.firstName) }}
You will need to add the widget with this and the label if you want a label to show. Full rendering for each row requires all three:
{{ form_label(form.firstName) }}
{{ form_errors(form.firstName) }}
{{ form_widget(form.firstName) }}

How to render form_rest() as hidden fields in Symfony2/Twig?

I have a Form class that contains many fields. I would like to render few of them and pass the left ones as hidden. How is this possible ?
I would like to do something like {{ form_rest(form, {'display': 'hidden'}) }} or <div display="hidden">{{ form_rest(form) }}</div>.
Example :
<form action="{{ path('fiche_intervention', {'rreid': rre.rreid}) }}" method="post" {{ form_enctype(form) }}>
{{ form_errors(form) }}
<div class="bloc-input">{{ form_label(form.rredatecommencement, "Date de retrait :") }}
{{ form_widget(form.rredatecommencement) }}
</div>
{# Some other fields... #}
{# ... #}
{# /Some other fields... #}
<div display="hidden">{{ form_rest(form) }}</div>
<input type="submit" />
</form>
You have to do it in you buildForm function, inside the "FormController". Just adding 'hidden' when you add the field is enough.
public function buildForm(FormBuilder $builder, array $options)
{
$builder->add('name');
$builder->add('email', 'email');
$builder->add('subject');
$builder->add('anyone', 'hidden');
}
Also you may set all your unneeded fields as rendered in your twig template:
<form action="{{ path('fiche_intervention', {'rreid': rre.rreid}) }}" method="post" {{ form_enctype(form) }}>
{{ form_errors(form) }}
<div class="bloc-input">{{ form_label(form.rredatecommencement, "Date de retrait :") }}
{{ form_widget(form.rredatecommencement) }}
</div>
{% do form.unneededfield1.setRendered %}
{% do form.unneededfield2.setRendered %}
{% do form.unneededfield3.setRendered %}
<div display="hidden">{{ form_rest(form) }}</div>
<input type="submit" />
</form>
form_rest() renders all non-rendered fields from your form. It just renders them as they are, so if you want to render remaining fields as 'hidden', you just have to define them as 'hidden' in your Form !
{{ form_end(form, {'render_rest': false}) }}
It's from the official documentation (v3.0) so it's pretty much best practise i guess.

Resources