I have a symfony3 project where I'm adding a custom class to some form fields via twig. This is all working fine except for the checkbox label. My custom class does not show in the label for the checkbox as expected.
EDIT: adding my form builder:
class ReferralFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('modality', EntityType::class, [
'class' => Modality::class,
'placeholder' => 'Choose modality',
'choice_label' => 'name',
])
->add('referralFromDoctor', EntityType::class, [
'class' => Doctor::class,
'placeholder' => 'Choose a doctor:',
'choice_label' => 'name',
])
->add('isFollowup', CheckboxType::class, [
'label' => 'Follow up visit?',
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Referral::class
]);
}
}
Here's my twig template:
{{ form_start(form) }}
<div id="js-order-wrapper">
{{ form_label(form.modality, 'Type', { 'label_attr': {'class': 'js-hidden-row'} }) }}
{{ form_widget(form.modality, { 'attr': {'class': 'js-hidden-row'} }) }}
{{ form_label(form.referralFromDoctor, 'Ordering clinician', { 'label_attr': {'class': 'js-hidden-row'} }) }}
{{ form_widget(form.referralFromDoctor, { 'attr': {'class': 'js-hidden-row'} }) }}
{{ form_label(form.isFollowup, 'Follow up?', { 'label_attr': {'class': 'js-hidden-row'} }) }}
{{ form_widget(form.isFollowup, { 'attr': {'class': 'js-hidden-row'} }) }}
</div>
{{ form_end(form) }}
and here is the rendered html:
<div id="js-order-wrapper">
<label class="js-hidden-row control-label required" for="referral_form_modality">Type</label>
<select id="referral_form_modality" name="referral_form[modality]" required="required" class="js-hidden-row form-control"><option value="">Choose modality</option></select>
<label class="js-hidden-row control-label required" for="referral_form_referralFromDoctor">Ordering clinician</label>
<select id="referral_form_referralFromDoctor" name="referral_form[referralFromDoctor]" required="required" class="js-hidden-row form-control"><option value="">Choose a doc</option></select
<div class="checkbox">
<label class="required">
<input type="checkbox" id="referral_form_isFollowup" name="referral_form[isFollowup]" required="required" class="js-hidden-row" value="1" /> Follow up visit?
</label>
</div>
</div>
As you can see, the class 'js-hidden-row' is correctly applied to the labels for the fields, but for the checkbox the class is not applied to the label. Seems like a bug to me.
Short of writing a custom block of code to render the checkbox, is there a better solution?
Related
I'm trying to change a EntityType form view for something look like: http://davidstutz.de/bootstrap-multiselect/#templates
I make change on my base.html.twig, by adding dependency, I make try bye using code exmaple on this twig file to see if all is fine and it's working.
Now the problem come when I make change on my _form.html.twig or in the Type.php file, actually after all my try I don't see where to make change.
My _form.html.twig
{{ form_start(form) }}
{{ form_widget(form) }}
{{ form_widget(form.Service) }}
<table width=100% cellpadding="10"><tr></tr><tr><td>
<button class="btn btn-success btn-icon-split">
<span class="icon text-white-50">
<i class="fas fa-save"></i>
</span>
</button>
</td>
{{ form_end(form) }}
My UtilisateursType.php
<?php
namespace App\Form;
use App\Entity\Utilisateurs;
use App\Entity\Services;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Doctrine\ORM\EntityRepository;
class UtilisateursType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('Nom')
->add('Login')
->add('PartagePerso')
->add('Service', EntityType::class, [
'class' => Services::class,
'query_builder' => function (EntityRepository $Service) {
return $Service->createQueryBuilder('u')
->orderBy('u.Nom', 'ASC');
},
'choice_label' => 'Nom',
'multiple' => true,
'expanded' => false,
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Utilisateurs::class,
]);
}
}
Thank for you help
Symfony will wrapper each field by an html element (<div>) and in order to modify this behaviour you have to override it.
see form_themes
first of all create a template eg: template/form/my_custom_entity_service.html.twig
{% use 'form_div_layout.html.twig' %}
{% block entity_row %}
{{ form_label(form) }}
<table width=100% cellpadding="10">
<tr>
<td>
{{ form_widget(form) }}
</td>
</tr>
</table>
{% endblock %}
then call it in your _form.html.twig
{% form_theme form 'form/my_custom_entity_service.html.twig' %}
{{ form_start(form) }}
{{ form_widget(form.Nom) }}
{{ form_widget(form.Login) }}
{{ form_widget(form. PartagePerso) }}
{{ form_widget(form.Service) }}
{{ form_end(form) }}
Note: the way you call the form in your code is wrong consider {{ form_rest(form) }}
I have a contact form and I'm trying to put a class to an input of my form.
This is in the ContactType:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', TextType::class);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Contact::class,
]);
}
And this in my twig:
{{ form_start(form) }}
{{ form_widget(form.name, {attr: {class: 'myclass', placeholder: 'name'} }) }}
{{ form_end(form) }}
I get this html:
<input type="text" class="form-control" id="contact_name" name="contact[name]" required="required" placeholder="name">
It's working for placeholder, but not to class. I have tried to put the attr in the builder and it is the same. Is the class form-control overwriting my class? How can I fix it?
I think you're using a bootstrap form theme, check into the config file.
and if the case, you can add this line on the top of your twig file :
{% form_theme form 'form_div_layout.html.twig' %}
Try this if it will help you
{{ form_start(form) }}
{{ form_widget(form.name, {'attr': {'class': 'input-text input-text--white', 'placeholder': 'name'} }) }}
{{ form_end(form) }}
I believe you can't define two attributes on form_wdiget. The way around this is doing both in the FormBuilder or one in the FormBuilder.
You can define attributes on a form element like so:
$builder
->add('name', TextType::class, [
'attr' => [
'class' => 'my-class',
],
]);
Note that for a CSS class, it must be in the array attr, not to be confused with a class as in your entity like on the EntityType::class.
Or
$builder
->add('name', TextType::class, [
'placeholder' => 'My place holder',
]);
So you could achieve both like:
$builder
->add('name', TextType::class, [
'attr' => [
'class' => 'my-class',
],
'placeholder' => 'My place holder',
]);
You can read more about form field attributes here.
You can read it from the official page:
https://symfony.com/doc/current/reference/forms/types/form.html#attr
Just add: {'attr': {'attribute name': 'value'}}
As shown below
{{ form_widget(form.propertyName, {'attr': {'placeholder': 'name'} }) }}
I have a form which has EntityType:class below in Symfony 3 or SF3, as you can see I am calling the function from method findAllActiveBuyingCurrencies from BranchCurrencyRepository.
->add('currency', EntityType::class, [
'class' => BranchCurrency::class,
'choice_value' => 'rate',
'choice_label' => function($currency){
return $currency->getName() . ' (' . $currency->getCode() .') - '.$currency->getRate().'';
},
'placeholder' => 'Choose currency',
'query_builder' => function (BranchCurrencyRepository $er) {
return $er->findAllActiveBuyingCurrencies();
},
])
The functions does it's thing and displays all currencies inside the form (Option)
But, I wanted to display all currencies and my problem is, only 25 currencies are displayed.
Please see my code displaying all currencies
// branchCurrenciesRepository
public function findAllActiveBuyingCurrencies() {
return $this->createQueryBuilder('currency')
->where('currency.type = :type')
->setParameter('type', BranchCurrencyConstant::Buying);
}
View
<div class="col-3">
<label for="" class="required">
<strong> Currency <span class="highlight-red"></span></strong>
</label>
{{ form_widget(form.currency) }}
{% if not form.currency.vars.valid %}
<p class="mt10" style="color: #DC2B1B;">{{ form.currency.vars.errors[0].message }}</p>
{% endif %}
</div>
For a template that includes a date field widget, non-date input fields will have their background colors changed per CSS. The same does not occur on the date widget. How should the background color of the date widget be effected? (Adding an attr array in the form class has no effect.)
A screenshot of the (small but real) difference:
Code samples:
Template:
<td>{{ form_widget(form.fname, {'attr': {'class':'smallform'}}) }}
<td>{{ form_widget(form.sname, {'attr': {'class':'smallform'}}) }}
<td>{{ form_widget(form.dateAdded, {'attr': {'class':'smallform'} }) }}
Form class:
->add('fname', null, array('required' => false))
->add('sname', null, array('required' => false))
->add('dateAdded', 'date', array(
'widget' => 'choice',
'format' => 'MM/dd/yyyy',
'pattern' => '{{ year }}-{{ month }}-{{ day }}',
'years' => range(Date('Y'), Date('Y') - 5),
'required' => false,
'data' => date_create(),
))
CSS:
.smallform {
background-color: #f5f5f5;
font-size: 9pt;
color: #000066;
border: 1px solid #CCCC99;
}
A less-than-subtle solution: modify the date widget in my application's customized copy of fields.html.twig. The more precise solution would be to define a specific widget for this, or figure out how to retain the class attribute all the way into the date widget:
{% block date_widget %}
{% spaceless %}
{% if widget == 'single_text' %}
{{ block('form_widget_simple') }}
{% else %}
<div {{ block('widget_container_attributes') }}>
{{ date_pattern|replace({
'{{ year }}': form_widget(form.year, {'attr': {'class':'smallform'}}),
'{{ month }}': form_widget(form.month, {'attr': {'class':'smallform'}}),
'{{ day }}': form_widget(form.day, {'attr': {'class':'smallform'}}),
})|raw }}
</div>
{% endif %}
{% endspaceless %}
{% endblock date_widget %}
Try:
->add('fname', null, array(
'required' => false,
'attr' => array('class' => 'smallform')
))
->add('sname', null, array(
'required' => false,
'attr' => array('class' => 'smallform')
))
->add('dateAdded', 'date', array(
'attr' => array('class' => 'smallform'), // ADDED
'widget' => 'choice',
'format' => 'MM/dd/yyyy',
'pattern' => '{{ year }}-{{ month }}-{{ day }}',
'years' => range(Date('Y'), Date('Y') - 5),
'required' => false,
'data' => date_create(),
))
also, view-source to make sure the classes are actually set in the html tags, it could be a problem with your CSS.
There is a problem with these lines:
<td>{{ form_widget(form.fname, {'attr': {'class':'smallform'}}) }}</td>
I dont think you can set a class on the entire widget, only for individual rows.
you can try this if you need to set the class via twig.
<form action="" method="">
{{ form_errors(form) }}
{{ form_row(form.fname, { 'attr': {'class': 'smallform' } }) }}
{{ form_row(form.sname, { 'attr': { 'class': 'smallform' } }) }}
<div class="smallform">
{{ form_row(form.dateAdded) }}
</div>
{{ form_rest(form) }}
<input type="submit" name="submit" value="Submit" />
</form>
I'm using the most recent version of Silex (without the .phar) with Doctrine DBAL installed, on this signup form page.
If I enter invalid details, it returns to that form as excepted. But if the details are valid, instead of redirecting to the /success/ page, it returns the same form again like nothing happened. The database has no entry received and Apache error log doesn't report any problems.
<?php
// ...
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Yaml\Parser;
use Silex\Provider\FormServiceProvider;
use Symfony\Component\Validator\Constraints as Assert;
// ...
$app->match('/signup/', function(Request $request) use($app, $page) {
$data = array('name' => 'John','surname' => 'Smith','telephone' => '00011112222');
$form = $app['form.factory']->createBuilder('form', $data)
->add('name', 'text', array(
'constraints' => array(
new Assert\NotBlank(),
new Assert\MinLength(2),
),
'invalid_message' => 'First name is too short, It should have 2 characters or more',
))
->add('surname', 'text', array(
'constraints' => array(
new Assert\NotBlank(),
new Assert\MinLength(2),
),
'invalid_message' => 'Surname is too short, It should have 2 characters or more',
))
->add('telephone', 'text', array(
'constraints' => array(
new Assert\NotBlank(),
new Assert\Regex("/[\d\-\ ]+/"),
new Assert\MinLength(11),
),
'invalid_message' => 'Please enter a valid phone number. Must have 11 digits and may contain dashes (-) or spaces.',
))
->getForm();
if ('POST' == $request->getMethod()) {
$form->bindRequest($request);
if ($form->isValid()) {
$data = $form->getData();
$app['db']->insert('signups', array(
'forename' => $data['name'],
'surname' => $data['surname'],
'telephone' => $data['telephone']
));
return $app->redirect('/success/');
}
}
$page['form'] = $form->createView();
return $app['twig']->render('signup.html.twig', $page);
}, 'POST|GET');
$app->match('/success/', function() use($app, $page) {
return $app['twig']->render('success.html.twig', $page);
}, 'POST|GET');
And the twig form
<form class="well" action="/signup/" method="post">
<fieldset>
<div class="control-group">
{% if (form_errors(form.name)) or (form_errors(form.surname)) or (form_errors(form.telephone)) %}
<div class="error-in-form">
<h5 style="color:#c00;">Please review the following errors:</h5>
<br />
<div>
<p class="help-msg"><span>First Name: </span></p>
<div class="error-msg">{{ form_errors(form.name) }}</div>
<div class="clearfix"></div>
</div>
<div>
<p class="help-msg"><span>Surname: </span></p>
<div class="error-msg">{{ form_errors(form.surname) }}</div>
<div class="clearfix"></div>
</div>
<div>
<p class="help-msg"><span>Telephone: </span></p>
<div class="error-msg">{{ form_errors(form.telephone) }}</div>
<div class="clearfix"></div>
</div>
</div>
{% endif %}
{{ form_label(form.name) }}
<div class="controls">
{{ form_widget(form.name, { 'attr': { 'class': 'input-medium' } } ) }}
{{ form_widget(form.surname, { 'attr': { 'class': 'input-medium' } } ) }}
</div>
</div>
<div class="control-group">
{{ form_label(form.telephone) }}
<div class="controls">
{{ form_widget(form.telephone, { 'attr': { 'class': 'input-fullwidth' } } ) }}
</div>
</div>
<p class="tnc">If you accepts the terms and conditions below, please proceed.</p>
<button id="big-red-button" type="submit" class="btn btn-danger btn-fullwidth">Submit ></button>
</fieldset>
</form>
Well, looks like I forgot to add {{ form_rest }} to the Twig form template.
Since I hadn't also included {{ form_errors(form) }} either, I couldn't see the error regarding the missing CSFP token, a hidden field that gets added to the form.