web-dev-qa-db-fra.com

Rendu personnalisé d'un champ "répété" à partir de Symfony 2 dans Twig

Je viens juste de commencer à utiliser Twig et j'essaie de créer un formulaire d'inscription. Pour ajouter un champ de mot de passe/ressaisir le mot de passe, j'utilise le type de fichier "répété":

->add('password', 'repeated', array(
    'type' => 'password',
    'invalid_message' => 'Passwords have to be equal.',
    'first_name'      => 'Password',
    'second_name'     => 'Re-enter password',
));

qui fonctionne comme prévu. Le problème que j'ai cependant, c'est que je veux ajouter des classes personnalisées, etc. à mon formulaire. Donc, mon modèle ressemble à ceci:

<form action="{{ path('register') }}" method="post" {{ form_enctype(form) }}>
    {{ form_errors(form) }}
    {{ form_errors(form.username) }}
    <div class="form-field">
        {{ form_label(form.username, null, { 'attr': {'class': 'form-label'} }) }}
        {{ form_widget(form.username, { 'attr': {'class': 'form-input'} }) }}
    </div>
    {{ form_errors(form.email) }}
    <div class="form-field">
        {{ form_label(form.email, null, { 'attr': {'class': 'form-label'} }) }}
        {{ form_widget(form.email, { 'attr': {'class': 'form-input'} }) }}
    </div>
    {{ form_errors(form.password) }}
    <div class="form-field">
        {{ form_label(form.password, null, { 'attr': {'class': 'form-label'} }) }}
        {{ form_widget(form.password, { 'attr': {'class': 'form-input'} }) }}
    </div>

    {{ form_rest(form) }}

    <input type="submit" class="contact-submit" />
</form>

cela fonctionne très bien pour tout sauf la partie mot de passe. Je veux rendre les deux champs séparément ici, maintenant ils sont juste rendus dans la même div.

Comment puis-je réparer ça? Est-il possible de sélectionner les champs séparés dans Twig? Ou suis-je en train de faire quelque chose de mal parce que je rencontre ce problème en premier lieu.

27
teuneboon

Après une supposition aléatoire, j'ai résolu mon propre problème. Je vais le poster ici pour que les autres qui pourraient répondre à cette question en cherchant aussi connaissent la réponse:

{% for passwordField in form.password %}
    <div class="form-field">
        {{ form_label(passwordField, null, { 'attr': {'class': 'form-label'} }) }}
        {{ form_widget(passwordField, { 'attr': {'class': 'form-input'} }) }}
    </div>
{% endfor %}
55
teuneboon

Si vous voulez séparer les deux champs de mots de passe d'une méthode répétée dans votre modèle de brindille, il vous suffit de rappeler leurs noms respectifs, comme suit:

{{ form_label(form.password.pass, "Password :") }}
{{ form_widget(form.password.pass) }}

{{ form_label(form.password.confirm, "Confirm :") }}
{{ form_widget(form.password.confirm) }}

Et bien sûr dans votre fonction:

/..
->add('password', 'repeated', array(
'first_name' => 'pass',
'second_name' => 'confirm',
'type' => 'password'
))

Cordialement.

25
Log

Cela fonctionne pour moi:

....
{{ form_errors(form.password.first) }}
<div class="form-field">
    {{ form_label(form.password.first, null, { 'attr': {'class': 'form-label'} }) }}
    {{ form_widget(form.password.first, { 'attr': {'class': 'form-input'} }) }}
</div>

{{ form_errors(form.password.second) }}
<div class="form-field">
    {{ form_label(form.password.second, null, { 'attr': {'class': 'form-label'} }) }}
    {{ form_widget(form.password.second, { 'attr': {'class': 'form-input'} }) }}
</div>
....
18
cslucano

Si vous utilisez Users Bundle, ils utilisent password.first et password.second. Essayez encore mieux d'utiliser votre profileur pour voir quelles variables proviennent de la vue et des contrôleurs.

3
Luis Lopes

Si vous souhaitez avoir des classes d'application pour vos étiquettes et vos entrées, vous pouvez personnaliser le rendu des étiquettes et des widgets. Vérifier http://symfony.com/doc/current/cookbook/form/form_customization.html

Si vous regardez ce fichier:

vendor/symfony/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig

Vous pouvez voir les valeurs par défaut pour tous les widgets. Pour obtenir spécifiquement ce dont vous avez besoin, vous pouvez remplacer le bloc generic_label pour ajouter une classe d'étiquette de formulaire:

{% block generic_label %}
{% spaceless %}
    {% if required %}
        {# We add form-label class in the next line! #}
        {% set attr = attr|merge({'class': attr.class|default('') ~ ' required form-label'}) %}
    {% endif %}
    <label{% for attrname,attrvalue in attr %} {{attrname}}="{{attrvalue}}"{% endfor %}>{{ label|trans }}</label>
{% endspaceless %}
{% endblock %}

Et widget_attributes bloque pour ajouter une classe de saisie de formulaire:

{% block widget_attributes %}
{% spaceless %}
    {# We add form-input class in the next line! #}
    {% set attr = attr|merge({'class': attr.class|default('') ~ ' form-input'}) %}
    id="{{ id }}" name="{{ full_name }}"{% if read_only %} disabled="disabled"{% endif %}{% if required %} required="required"{% endif %}{% if max_length %} maxlength="{{ max_length }}"{% endif %}{% if pattern %} pattern="{{ pattern }}"{% endif %}
    {% for attrname,attrvalue in attr %}{{attrname}}="{{attrvalue}}" {% endfor %}
{% endspaceless %}
{% endblock widget_attributes %}

Avec ces deux modèles, toutes vos entrées doivent être restituées avec les classes dont vous avez besoin, sans avoir à répéter les paramètres "attr" sur tous vos formulaires.

Je n'ai pas essayé, mais cela devrait régler le problème de terrain répété. Même si ce n'était pas le cas, vous pouvez créer un modèle repeat_widget et/ou repeat_row pour personnaliser le rendu du widget répété, fixant ainsi ce widget pour tous les formulaires l'utilisant.

0
Jens