Symfony2表单生成器 - 删除标签,使其占位符

Symfony2表单生成器 - 删除标签,使其占位符

问题描述:

I am playing with Symfony's form builder, and I can't find a way to not display a label. Further, I am interested in actually setting a placeholder for each input box. Is this possible? I have researched a bit and found nothing.

My form:

<form action="{{ path('searchPeople') }}" method="post" class="form-inline">
    {{ form_errors(form) }}

    {{ form_row(form.first_name) }}
    {{ form_row(form.last_name) }}

    {{ form_rest(form) }}

    <br />
    <button type="submit" class="btn btn-primary" /><i class="icon-search"></i>Search</button>
</form>

EDIT: Solved! All of the solutions below helped, but I gave the answer to the primary helpful comment. I appreciate all of the help. For anyone else that comes across this, this is my final working code:

<form action="{{ path('searchPeople') }}" method="post" class="form-inline">
    {{ form_errors(form) }}

    {{ form_errors(form.first_name) }}
    {{ form_widget(form.first_name, {'attr': {'placeholder': 'First Name'} }) }}

    {{ form_errors(form.last_name) }}
    {{ form_widget(form.last_name, {'attr': {'placeholder': 'Last Name'} }) }}

    {{ form_rest(form) }}

    <br />
    <button type="submit" class="btn btn-primary" /><i class="icon-search icon-white"></i>Search</button>
</form>

If you're outputting the field with form_rest you'll have to set the label for the the field to false in the form builder with something like

$builder->add('first_name', 'text', array(
    'label' => false,
));

If you output the fields individually, you can omit the form_label for that field in the twig template, or set it to an empty string.

{{ form_label(form.first_name, '') }}

I did this recently! :) You'll want to create a new fields template, for form_row and one for form_widget. Then remove the form_label part, and add your placeholder.

http://symfony.com/doc/current/cookbook/form/form_customization.html

You can do it per field, or set it for all of them.

Or you can also skip the removing the form_label from the form_row template, and just do form_widget() where you're currently calling form_row()

You must render the form manually.

Here's an example:

<form id="form-message" action="{{ path('home') }}" method="post" {{ form_enctype(form) }}>
  {{ form_label(form.name) }}
  {% if form_errors(form.name) %}
    <div class="alert alert-error">
      {{ form_errors(form.name) }}
    </div>
  {% endif %}
  {{ form_widget(form.name) }}
  {{ form_row(form._token) }}
  <input type="submit" class="btn" value="Submit">
</form>

Related documentation

for other that come across this label-question: you could use form theme to override the form_row tag for every form you want. However I recommend to just set it invisible for page reader optimization. my example with bootstrap:

{% block form_row %}
    {% spaceless %}
            {{ form_label(form, null, {'label_attr': {'class': 'sr-only'}}) }}
            {{ form_errors(form) }}
            {{ form_widget(form) }}
    {% endspaceless %}
{% endblock form_row %}

don't forget to include your formtheme in config.yml and template.

Convert label to placeholder

{% use 'form_div_layout.html.twig' with widget_attributes as base_widget_attributes %}
{% block widget_attributes %}
    {% set attr = {'placeholder': label|trans({}, translation_domain)} %}
    {{- block('base_widget_attributes') -}}
{% endblock widget_attributes %}

Expanding on Léo's answer:

{% use 'form_div_layout.html.twig' %}
{% block widget_attributes %}
{% spaceless %}
    {% set attr = attr|merge({'placeholder': label}) %}
    {{ parent() }}
{% endspaceless %}
{% endblock widget_attributes %}

trans filter has been removed because it is included in the parent.

I know it's already answered, but might help somebody who is looking for a different solution for placeholders, if you don't want to change anything in your twig template:

$builder->add(
    'name',
    'text', 
     array(
        'attr' => array(
             'placeholder' => 'Your name',
        ),
        'label' => false,
     )
);

For those NOT using form_row, you can always add the placeholder as an attribute directly when adding the input to the builder. Like so:

$task = new Task();
$form = $this->createFormBuilder($task)
            ->add('first_name', 'text', array(
                      'required' => true,
                      'trim' => true,
                      'attr' => array('placeholder' => 'Lorem Ipsum')
        )->getForm();

Symfony 2.8 & above

  1. Remove form_label

    {% block form_row %}
    <div>
        {{ form_errors(form) }}
        {{ form_widget(form) }}
    </div>
    {% endblock form_row %}
    
  2. Add placeholder attribute

    {% block form_widget_simple %}
        {% set type = type|default('text') %}
        <input placeholder="{{ translation_domain is same as(false) ? label : label|trans({}, translation_domain) }}" type="{{ type }}" {{ block('widget_attributes') }} {% if value is not empty %}value="{{ value }}" {% endif %}/>
    {% endblock form_widget_simple %}
    

To sums it up:

  • Titi's answer is the most simple ;

  • Mick, Léo & Quolonel's answers are the most effective but are incomplete (for symfony > 2.6) :

If you use the label_format option in your *Type::configureOptions, their solution does not work. You need to add the content of the form_label block to handle all the label possibilities. The full & most effective answer (code used w/ symfony 3.3) :

  1. Remove form_label

    {% block form_row %}
    <div>
        {{ form_errors(form) }}
        {{ form_widget(form) }}
    </div>
    {% endblock form_row %}
    
  2. Edit the widget_attribute block

    {% block widget_attributes %}
        {% spaceless %}
            {% if label is not same as(false) -%}
                {% if label is empty -%}
                    {%- if label_format is not empty -%}
                        {% set label = label_format|replace({
                            '%name%': name,
                            '%id%': id,
                        }) %}
                    {%- else -%}
                        {% set label = name|humanize %}
                    {%- endif -%}
                {%- endif -%}
    
                {% set attr = attr|merge({'placeholder': label}) %}
            {%- endif -%}
    
            {{ parent() }}
        {% endspaceless %}
    {% endblock widget_attributes %}
    

Notes :

  • Do not translate the labels into the widget_attributes block, otherwise they will appear as missing translations.

  • The solution does not work for checkboxes or radio buttons, you'll want to add something like :

    {%- block checkbox_widget -%}
        {{ parent() }}
        {{- form_label(form) -}}
    {%- endblock checkbox_widget -%}
    

You can also copy the labels into the placeholder attribute before rendering the form:

$formView = $form->createView();

foreach($formView->getIterator() as $item) {
    /** @var $item FormView */
    if ($item->vars['label']) {
        $item->vars['attr']['placeholder'] =$item->vars['label'];
    }
}

Bootstrap Forms

In my case best is mix aswers of @Cethy and @Quolonel Questions

{% form_theme form _self %}
{% use 'bootstrap_4_layout.html.twig' %}

{% block widget_attributes %}          {#   set placeholder   #}
    {% spaceless %}
        {% set attr = attr|merge({'placeholder': label}) %}
        {{ parent() }}
    {% endspaceless %}
{% endblock widget_attributes %}

{% block form_row %}                   {#   remove label   #}
    <div class="form-group">
        {{ form_errors(form) }}
        {{ form_widget(form) }}
    </div>
{% endblock form_row %}

It looks the following

enter image description here

It works with translations