Where can I change the form text box size? - symfony

I make form in Controller like this below.
$form = $this->createFormBuilder($row)
->add('comment',null,array('label' => 'input comment'))
then in the twig file...
{{form_widget(form.commentToMutor)}}
It shows text input box,but it is too small.
How to change size of TextBox

Extending #manseuk 's answer (I don't have enough reputation to post a comment), you can also specify the html style attribute inside the form builder, if you preffer:
$form = $this->createFormBuilder($row)
->add('comment', null, array(
'label' => 'input comment',
'attr' => array('style' => 'width: 200px')
)
);
Edited from html attribute for width to html style attribute.

You could add a class to the form field :
$form = $this->createFormBuilder($row)
->add('comment',null,array(
'label' => 'input comment',
'attr' => array('class' => 'myclass')
)
);
and then create the CSS relevant to that class :
.myclass {
width: 200px;
}
Docs for the attr attribute here

Or in the twig file:
{# Define CSS class and call #}
{{ form_widget(form.commentToMutor, { 'attr': {'class': 'myclass'} }) }}
{# ... or enter width directly #}
{{ form_widget(form.commentToMutor, { 'attr': {'style': 'width: 200px'} }) }}
More here

Setting the width directly did not work for me. I had to set it through the style. Of course this is an easy fix, the correct way is to use a css class like others have suggested.
$form = $this->createFormBuilder($row)
->add('comment', null, array(
'label' => 'input comment',
'attr' => array('style' => 'width:200px')
)
);

Related

Symfony2 : Radio buttons in a collection

In my application, I created a form using the collection field type :
$builder->add('tags', 'collection', array(
'type' => new TagType(),
'label' => false,
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false
));
With some JQuery, this code works correctly, but now I would like to select one of this dynamic tag to make it "the main tag".
In my Tag entity, I added a boolean attribute which define if the tag is the main or not :
/**
* #ORM\Column(name="main", type="boolean")
*/
private $main;
But in my view, each row now contains a checkbox. So I can select more than one main tag. How to transform this checkbox in radio button please ?
You're not tackling the problem from the right angle. If there should be a main tag, then this property should not be added in the Tag entity itself, but in the entity that contains it!
I'm speaking of the data_class entity related to the form having the tags attribute. This is the entity that should have a mainTag property.
If defined properly, this new mainTag attribute will not be a boolean, for it will contain a Tag instance, and thus will not be associated to a checkbox entry.
So, the way I see it, you should have a mainTag property containing your instance and a tags property that conatins all other tags.
The problem with that is that your collection field will no longer contain the main tag. You should thus also create a special getter getAllTags that will merge your main tag with all others, and change your collection definition to:
$builder->add('allTags', 'collection', array(
'type' => new TagType(),
'label' => false,
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false
));
Now, how do we add the radio boxes, you may ask? For this, you will have to generate a new field:
$builder->add('mainTag', 'radio', array(
'type' => 'choice',
'multiple' => false,
'expanded' => true,
'property_path' => 'mainTag.id', // Necessary, for 'choice' does not support data_classes
));
These are the basics however, it only grows more complex from here. The real problem here is how your form is displayed. In a same field, you mix the usual display of a collection and the display of a choice field of the parent form of that collection. This will force you to use form theming.
To allow some room to reusability, you need to create a custom field. The associated data_class:
class TagSelection
{
private mainTag;
private $tags;
public function getAllTags()
{
return array_merge(array($this->getMainTag()), $this->getTags());
}
public function setAllTags($tags)
{
// If the main tag is not null, search and remove it before calling setTags($tags)
}
// Getters, setters
}
The form type:
class TagSelectionType extends AbstractType
{
protected buildForm( ... )
{
$builder->add('allTags', 'collection', array(
'type' => new TagType(),
'label' => false,
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false
));
// Since we cannot know which tags are available before binding or setting data, a listener must be used
$formFactory = $builder->getFormFactory();
$listener = function(FormEvent $event) use ($formFactory) {
$data = $event->getForm()->getData();
// Get all tags id currently in the data
$choices = ...;
// Careful, in PRE_BIND this is an array of scalars while in PRE_SET_DATA it is an array of Tag instances
$field = $this->factory->createNamed('mainTag', 'radio', null, array(
'type' => 'choice',
'multiple' => false,
'expanded' => true,
'choices' => $choices,
'property_path' => 'mainTag.id',
));
$event->getForm()->add($field);
}
$builder->addEventListener(FormEvent::PRE_SET_DATA, $listener);
$builder->addEventListener(FormEvent::PRE_BIND, $listener);
}
public function getName()
{
return 'tag_selection';
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'TagSelection', // Adapt depending on class name
// 'prototype' => true,
));
}
}
Finally, in the form theme template:
{% block tag_selection_widget %}
{% spaceless %}
{# {% set attr = attr|default({})|merge({'data-prototype': form_widget(prototype)}) %} #}
<ul {{ block('widget_attributes') }}>
{% for child in form.allTags %}
<li>{{ form_widget(form.mainTag[child.name]) }} {{ form_widget(child) }}</li>
{% endfor %}
</ul>
{% endspaceless %}
{% endblock tag_selection_widget %}
Lastly, we need to include that in your parent entity, the one that originally contained tags:
class entity
{
// Doctrine definition and whatnot
private $tags;
// Doctrine definition and whatnot
private $mainTag;
...
public setAllTags($tagSelection)
{
$this->setMainTag($tagSelection->getMainTag());
$this->setTags($tagSelection->getTags());
}
public getAllTags()
{
$ret = new TagSelection();
$ret->setMainTag($this->getMainTag());
$ret->setTags($this->getTags());
return $ret;
}
...
}
And in your original form:
$builder->add('allTags', new TagSelection(), array(
'label' => false,
));
I recognize the solution I propose is verbose, however it seems to me to be the most efficient. What you are trying to do cannot be done easily in Symfony.
You can also note that there is an odd "prototype" option in the comment. I just wanted to underline a very useful property of "collection" in your case: the prototype option contains a blank item of your collection, with placeholders to replace. This allow to quickly add new items in a collection field using javascript, more info here.
This is not the right solution, but since you are using jQuery to add/remove...
TagType
->add('main', 'radio', [
'attr' => [
'class' => 'toggle'
],
'required' => false
])
jQuery
div.on('change', 'input.toggle', function() {
div
.find('input.toggle')
.not(this)
.removeAttr('checked');
});
http://jsfiddle.net/coma/CnvMk/
And use a callback constraint to ensure that there is only one main tag.
First thing you should wary about - its that in your scheme if tag become main for one entity it will be main for all entities because the tag store attribute and few entities can be tagged with one tag.
So simplest decision here is to create new property main_tag near tags in your entity, create hidden field main_tag(with id to Tag Data transformer) in your form and populate and change this field with jQuery(for example set it on tag click or clear on main tag delete)
Maybe there is something to do with the multiple form option, but it might require a little tweaking on your collection form and tag entity.

Custom Symfony ChoiceList way of rendering choices (grouped in divs)

I have a choice form field that has a lot of options that I need to group somehow so that they will be rendered divided in groups, maybe placed inside different divs.
I'm currently trying to implement the ChoiceListInterface to achieve that, but I don't know how to implement the methods so I can render the choices divided by groups, but the docs does not clarify how to do that..
The choices always get rendered together.
You have this array
$grouped_choices = array(
'Swedish Cars' => array(
'volvo' => 'Volvo',
'saab' => 'Saab',
),
'German Cars' => array(
'mercedes' => 'Mercedes',
'audi' => 'Audi'
)
);
First way: quick and simple
$builder->add($name, 'choice', array(
'choices' => $grouped_choices),
)
But I don't thinks it works with 'expanded' => true
So there is another way, more customizable (maybe more dirty)
In your FormType
foreach($grouped_choices as $name => $choices) {
$builder->add($name, 'choice', array(
'choices' => $choices),
'expanded' => true, //custom the widgets like you wants
);
}
Let the controller send the array to the view, then in the view
{% for name, choices in grouped_choices %}
<div class="whatever">
{{ form_row(name) }}
</div>
{% endfor %}

How to disable HTML escaping of labels in KnpMenuBundle

I want to render an HTML label like:
$menu->addChild('Dashboard', array(
'route' => 'dashboard',
'label' => '<i class="fa-icon-bar-chart"></i><span class="hidden-tablet"> Dashboard</span></a>',
'extra' => array('safe_label' => true)
)
);
And I've pass the proper option while rendering:
{{ knp_menu_render('WshCmsHtmlBundle:Builder:mainMenu', {'allow_safe_labels': true} ) }}
But my label is still being escaped. What am I doing wrong?
Ok, the answer is!
You set up extra items on menu item not by 'extra' key but by 'extras' key.
So when you setup the item like this:
$menu->addChild('Dashboard', array(
'route' => 'dashboard',
'label' => '<i class="fa-icon-bar-chart"></i><span class="hidden-tablet"> Dashboard</span></a>',
'extras' => array('safe_label' => true)
)
);
it works fine!
There's two steps to achieve this.
1. MenuBuilder
You have to set safe_label to true in extras. Note that you can now write HTML in your label.
$menu->addChild('Home<i><b></b></i>', array(
'route' => 'homepage',
'extras' => array(
'safe_label' => true
),
));
2. Twig
You have to filter the output of knp_menu_render() so that it prints raw HTML (see documentation).
{{ knp_menu_render('main', {'allow_safe_labels': true}) | raw }}
Warning
Please be aware that this may be dangerous. From the documentation:
Use it with caution as it can create some XSS holes in your application if the label is coming from the user.
I used FyodorX's method to add a strong tag. It works like a charm but I must say that the raw filter is not necessary

Symfony2 - custom css for select in forms

i have a little problem with the rendering of my forms.
I would like my different select box have different size.
<div >
{{ form_label(form.date_of_birth, 'date de naissance') }}
{{ form_widget(form.date_of_birth )}}
</div>
<div >
{{ form_label(form.Alimentation, 'Alimentation') }}
{{ form_widget(form.Alimentation)}}
</div>
This two widgets renders select box. I want the two to have a different size, one large, one thin.. But, i can't directly set the style of the , and set the width of the div does nothing.
I also tried this:
->add('date_of_birth', 'date', array('required' => false, 'attr' => array('style' => 'width:330px' ),
'widget' => 'choice',
'format' => 'dd-MM-yyyy',
'years' => range(1970,2012)))
This does nothing.
Explained in Twig Template Form Function Reference http://symfony.com/doc/current/reference/forms/twig_reference.html
{{ form_widget(form.name, { 'attr' : { 'class' : 'yourClass' } }) }}
Now you have added a class attribute to your form field with yourClass as css class. So you can style your field using css.

Symfony 1.4. How to add attributes of fields to the embedded form?

I embed one form to another. I need to add HTML attributes to the fields embedded form.
Trying to do so:
$this->widgetschema['email'] = new sfWidgetFormInputText(array(), array('class' => 'email'));
but it does not work.
Did you try it this way?
creating a class
class YourForm extends sfForm {
$array= array('array');
$this->setWidgets(array(
'field1' => new sfWidgetFormSelect(array('choices' => $array), array('placeholder' => 'field1', 'required' => 'true', 'data-empty' => 'U did not enter field1!')),
'email_address' => new sfWidgetFormInputText(array('type' => 'email'), array())
));
}
You can even change the type in the first array. Then include your form in the actions by calling it like
$this->form = new YourForm();
Then echo your form in the template:
<?php echo $form; ?>
I hope this helps. I use it like this as well, to add extra attributes to use in javascript.

Resources