form render custom symfony2 - symfony

hi i am trying to make a form with validations.
I have this form:
<form class="formulario" id="modificarmedico" action="{{ path('medico_update', { 'id': entity.id }) }}" method="post" {{ form_enctype(edit_form) }}>
<div id="mio_miobundle_medicotype">
{{ form_row(edit_form.username) }}
{{ form_row(edit_form.dni) }}
{{ form_row(edit_form.nombre) }}
{{ form_row(edit_form.apellido1) }}
{{ form_row(edit_form.apellido2) }}
{{ form_row(edit_form.localidad) }}
{{ form_row(edit_form.provincia) }}
{{ form_row(edit_form.direccion) }}
{{ form_row(edit_form.email) }}
{{ form_row(edit_form.telefono) }}
{{ form_row(edit_form.movil) }}
{{ form_row(edit_form.titulacion)}}
{{ form_row(edit_form.numero)}}
{{ form_row(edit_form.fechaalta)}}
{{ form_row(edit_form.idioma)}}
{{ form_row(edit_form.tema)}}
{{ form_row(edit_form.color)}}
{% if is_granted('ROLE_A') %}
{% if entity.id == app.user.id %}
{{ form_row(edit_form.password) }}
{{ form_errors(form.password) }}
<div class="empoculto">
{{ form_row(edit_form.activo) }}
{{ form_row(edit_form.generar) }}
</div>
{% else %}
{{ form_row(edit_form.generar) }}
{{ form_row(edit_form.activo) }}
<div class="empoculto">
{{ form_row(edit_form.password) }}
</div>
{% endif %}
{% else %}
{{ form_row(edit_form.password) }}
{{ form_row(edit_form.password) }}
<div class="empoculto">
{{ form_row(edit_form.generar) }}
{{ form_row(edit_form.activo) }}
</div>
{% endif %}
but the password errors shows me outside the div. not so with the other fields:
<div>
<label for="mio_miobundle_medicotype_movil" class=" required">Móvil</label>
<ul>
<li>El campo debe tener 9 números.</li>
<li>El campo debe tener sólo números.</li>
</ul>
<input type="text" id="mio_miobundle_medicotype_movil" name="mio_miobundle_medicotype[movil]" required="required" maxlength="9" value="fgadfg" />
</div>
<div><label for="mio_miobundle_medicotype_color" class=" required">Color*</label><input type="text" id="mio_miobundle_medicotype_color" name="mio_miobundle_medicotype[color]" required="required" value="#1153ed" /></div>
<ul>
<li>Las contraseñas deben ser iguales.</li>
</ul>
<div><label for="mio_miobundle_medicotype_password_Nueva contraseña" class=" required">Nueva contraseña</label><input type="password" id="mio_miobundle_medicotype_password_Nueva contraseña" name="mio_miobundle_medicotype[password][Nueva contraseña]" required="required" /></div>
<div><label for="mio_miobundle_medicotype_password_Repite contraseña" class=" required">Repite contraseña</label><input type="password" id="mio_miobundle_medicotype_password_Repite contraseña" name="mio_miobundle_medicotype[password][Repite contraseña]" required="required" /></div>
i tried form_bubbling symfony2 but not solve my problem.
thanks.

Your if statement puts the errors in the div in one case and outside the div in the other (Actually it can't be determined since you did not post the entire form.)
{% if entity.id == app.user.id %}
{{ form_row(edit_form.password) }}
{{ form_errors(form.password) }} {# part of only one condition #}
<div class="empoculto"> {# specifically handled here #}
{{ form_row(edit_form.activo) }}
{{ form_row(edit_form.generar) }}
</div>
{% else %}
{{ form_row(edit_form.generar) }}
{{ form_row(edit_form.activo) }}
<div class="empoculto"> {# how to handle errors #}
{{ form_row(edit_form.password) }} {# not specified here #}
</div> {# probably handled by #}
{% endif %} {# form default #}
Also
{{ form_errors(form.password) }}
should probably be
{{ form_errors(edit_form.password) }}

Related

form field label is displaying twice

I'm using macro to display a collection of videos in my form.
Form
{% import "macros/prototype.html.twig" as prototype %}
{{ form_start(form) }}
<div class="row">
<div class="col-md-6">
{{ form_row(form.title) }}
{{ form_row(form.description) }}
<fieldset class="form-group">
{{ form_label(form.videos) }}
<div id="course_videos" class="collection_holder" data-prototype="{{ prototype.tagCollectionLinkItem(form.videos.vars.prototype)|e }}">
{% for video in form.videos.children %}
{{ prototype.tagCollectionLinkItem(video) }}
{% endfor %}
</div>
<button type="button" id="add-video-btn" data-target-collection="#{{ form.videos.vars.id }}" class="btn btn-sm btn-info"><i class="la la-plus"></i> {{ 'course.buttons.add_video' | trans({}, 'labels') }}</button>
</fieldset>
</div>
</div>
<hr>
<input type="submit" class="btn m-btn--pill at-btn--primary pull-right" value="{{ button_name }}">
{{ form_end(form) }}
Macro
{% macro tagCollectionFileItem(item) %}
<fieldset class="form-group">
<div id="{{ item.vars.id }}">
{% if item.uploadedFile.vars.file_url or item.uploadedFile.vars.image_url %}
{{ form_errors(item.uploadedFile) }}
{{ form_widget(item.uploadedFile, {'attr': {'hidden': true}}) }}
{% else %}
<div class="custom-file">
{{ form_widget(item.uploadedFile) }}
{{ form_label(item.uploadedFile, item.uploadedFile.vars.label, {'label_attr': {'class': 'custom-file-label'}}) }}
</div>
{% endif %}
</div>
</fieldset>
{% endmacro %}
form_end makes form.videos label to display twice. I guess because I never used form_widget(form.videos) so form_end makes it appears. Should I replace my macro with a form theme?
Because you never rendered form.video with the widget you need to set the field as rendered. Just use {{ do form.videos.setRendered }} and you are good to go

Text columns in front of form using {{form_label()}}

I am trying to reuse this old code to make some forms:
In a form.html.twig
<div class="row" style='margin-bottom: 5px'>
<div style='white-space:nowrap'>
<div class='col-xs-2'></div>
<div class='col-xs-3' style='border-bottom:1px solid black;padding-bottom: 14px'><div style='float:right'>{{ form_label(form.class.variable, 'Text on one column and text on another column', {'label_attr':{'style':'margin-top:5px'}})}}</div>
<div class='col-xs-3' style='border-bottom:1px solid black;padding-bottom: 5px'>{{ form_widget(form.class.variable, {'attr':{'style':'width:95px','placeholder':'RAW value'}})}}</div>
<div class='col-xs-3'></div>
</div>
I would like to have two columns before the form like on this picture:
Thank you for the hints!
You will need to customise your form_label block.
Have a look at the example here
EDIT:
Roughly, you're after something like this:
Your form theme (say, two_column_labels.html.twig):
{% extends 'form_div_layout.html.twig' %}
{% block form_row %}
<div class="row">
<div class="col-sm-6">
{{ form_label(form) }}
</div>
<div class="col-sm-3">
{{ form_errors(form) }}
</div>
<div class="col-sm-3">
{{ form_widget(form) }}
</div>
</div>
{% endblock form_row %}
{% block form_label %}
{% if label_attr.extra_label is defined %}
<div class="row">
<div class="col-sm-6">
{% set orig_label = label %}
{% set new_label_attr = [] %}
{% for key,value in label_attr %}
{% if key != 'extra_label' %}
{% set new_label_attr = new_label_attr|merge({(key): value}) %}
{% else %}
{% set label = value %}
{% endif %}
{% endfor %}
{% set label_attr = new_label_attr %}
{{ parent() }}
{% set label = orig_label %}
</div>
<div class="col-sm-6">
{{ parent() }}
</div>
</div>
{% else %}
{{ parent() }}
{% endif %}
{% endblock form_label %}
In your form field definition in your form class:
'label' => 'Second Label',
'label_attr' => array('extra_label' => 'First Label'),
In your form template:
{% form_theme form 'two_column_labels.html.twig' %}

twig print field multiple image in field templates

Here, I have attached my code
<div{{ attributes }}>
{% if not label_hidden %}
<div{{ title_attributes.addClass('field-label') }}>{{ label }}</div>
{% endif %}
<div{{ content_attributes.addClass('gall-wrp') }}>
{% for item in items %}
<a class="gall-img" href="{{ file_url(element['#object'].field_multiple_image.0.entity.uri.value) }}">
<img src="{{ file_url(element['#object'].field_multiple_image.0.entity.uri.value) }}"></a>
{% endfor %}
</div>
</div>
How to change {{ file_url(element['#object'].field_multiple_image.0.entity.uri.value) }} dynamically change value of 0.
.0 is the same than [0]. You can use:
{{ file_url(element['#object'].field_multiple_image.[yourVar].entity.uri.value) }}
Here, I have fixed this,
<div{{ attributes }}>
{% if not label_hidden %}
<div{{ title_attributes.addClass('field-label') }}>{{ label }}</div>
{% endif %}
<div{{ content_attributes.addClass('gall-wrp') }}>
{% for item in element['#object'].field_multiple_image %}
<a class="gall-img" href="{{ file_url(item.entity.uri.value) }}">
<img src="{{ file_url(item.entity.uri.value) }}"></a>
{% endfor %}
</div>
</div>

Customize SonataAdminBundle base_edit_form.html.twig

I would like to show the map in the form generated by Sonata Admin Bundle
This is my formMapper,
class PlaceInfoAdmin extends Admin
{
public function configureFormFields(FormMapper $formMapper)
{
$formMapper
->with('General')
->add('lati')
->add('longi')
->add('name')
I am using ivory google map API.
Simplifying what I want to do,
put this code at the last of template used by PlaceInfoAdmin
{{ ivory_google_api([
data.map,
data.form.field.vars['autocomplete']
])}}
put this code between rendered the cide of longi and name.
{{ ivory_google_map(data.map) }}
Now I research the twig files and found out maybe form is rendered by base_edit_form.html.twig,
However where should I alter?? or How can I find this twig is called by PlaceInfoAdmin?? (not by another ****Admin class)
{% block form %}
{{ sonata_block_render_event('sonata.admin.edit.form.top', { 'admin': admin, 'object': object }) }}
{% set url = admin.id(object) is not null ? 'edit' : 'create' %}
{% if not admin.hasRoute(url)%}
<div>
{{ "form_not_available"|trans({}, "SonataAdminBundle") }}
</div>
{% else %}
<form
{% if sonata_admin.adminPool.getOption('form_type') == 'horizontal' %}class="form-horizontal"{% endif %}
role="form"
action="{% block sonata_form_action_url %}{{ admin.generateUrl(url, {'id': admin.id(object), 'uniqid': admin.uniqid, 'subclass': app.request.get('subclass')}) }}{% endblock %}"
{% if form.vars.multipart %} enctype="multipart/form-data"{% endif %}
method="POST"
{% if not sonata_admin.adminPool.getOption('html5_validate') %}novalidate="novalidate"{% endif %}
{% block sonata_form_attributes %}{% endblock %}
>
{{ include('SonataAdminBundle:Helper:render_form_dismissable_errors.html.twig') }}
{% block sonata_pre_fieldsets %}
<div class="row">
{% endblock %}
{% block sonata_tab_content %}
{% set has_tab = ((admin.formtabs|length == 1 and admin.formtabs|keys[0] != 'default') or admin.formtabs|length > 1 ) %}
<div class="col-md-12">
{% if has_tab %}
<div class="nav-tabs-custom">
<ul class="nav nav-tabs" role="tablist">
{% for name, form_tab in admin.formtabs %}
<li{% if loop.index == 1 %} class="active"{% endif %}><i class="fa fa-exclamation-circle has-errors hide" aria-hidden="true"></i> {{ name|trans({}, form_tab.translation_domain ?: admin.translationDomain) }}</li>
{% endfor %}
</ul>
<div class="tab-content">
{% for code, form_tab in admin.formtabs %}
<div class="tab-pane fade{% if loop.first %} in active{% endif %}" id="tab_{{ admin.uniqid }}_{{ loop.index }}">
<div class="box-body container-fluid">
<div class="sonata-ba-collapsed-fields">
{% if form_tab.description != false %}
<p>{{ form_tab.description|raw }}</p>
{% endif %}
{{ form_helper.render_groups(admin, form, form_tab['groups'], has_tab) }}
</div>
</div>
</div>
{% endfor %}
</div>
</div>
{% else %}
{{ form_helper.render_groups(admin, form, admin.formtabs['default'].groups, has_tab) }}
{% endif %}
</div>
{% endblock %}
{% block sonata_post_fieldsets %}
</div>
{% endblock %}
{{ form_rest(form) }}
{% block formactions %}
<div class="sonata-ba-form-actions well well-small form-actions">
{% block sonata_form_actions %}
{% if app.request.isxmlhttprequest %}
{% if admin.id(object) is not null %}
<button type="submit" class="btn btn-success" name="btn_update"><i class="fa fa-save" aria-hidden="true"></i> {{ 'btn_update'|trans({}, 'SonataAdminBundle') }}</button>
{% else %}
<button type="submit" class="btn btn-success" name="btn_create"><i class="fa fa-plus-circle" aria-hidden="true"></i> {{ 'btn_create'|trans({}, 'SonataAdminBundle') }}</button>
{% endif %}
{% else %}
{% if admin.supportsPreviewMode %}
<button class="btn btn-info persist-preview" name="btn_preview" type="submit">
<i class="fa fa-eye" aria-hidden="true"></i>
{{ 'btn_preview'|trans({}, 'SonataAdminBundle') }}
</button>
{% endif %}
{% if admin.id(object) is not null %}
<button type="submit" class="btn btn-success" name="btn_update_and_edit"><i class="fa fa-save" aria-hidden="true"></i> {{ 'btn_update_and_edit_again'|trans({}, 'SonataAdminBundle') }}</button>
{% if admin.hasroute('list') and admin.isGranted('LIST') %}
<button type="submit" class="btn btn-success" name="btn_update_and_list"><i class="fa fa-save"></i> <i class="fa fa-list" aria-hidden="true"></i> {{ 'btn_update_and_return_to_list'|trans({}, 'SonataAdminBundle') }}</button>
{% endif %}
{% if admin.hasroute('delete') and admin.isGranted('DELETE', object) %}
{{ 'delete_or'|trans({}, 'SonataAdminBundle') }}
<a class="btn btn-danger" href="{{ admin.generateObjectUrl('delete', object) }}"><i class="fa fa-minus-circle" aria-hidden="true"></i> {{ 'link_delete'|trans({}, 'SonataAdminBundle') }}</a>
{% endif %}
{% if admin.isAclEnabled() and admin.hasroute('acl') and admin.isGranted('MASTER', object) %}
<a class="btn btn-info" href="{{ admin.generateObjectUrl('acl', object) }}"><i class="fa fa-users" aria-hidden="true"></i> {{ 'link_edit_acl'|trans({}, 'SonataAdminBundle') }}</a>
{% endif %}
{% else %}
{% if admin.hasroute('edit') and admin.isGranted('EDIT') %}
<button class="btn btn-success" type="submit" name="btn_create_and_edit"><i class="fa fa-save" aria-hidden="true"></i> {{ 'btn_create_and_edit_again'|trans({}, 'SonataAdminBundle') }}</button>
{% endif %}
{% if admin.hasroute('list') and admin.isGranted('LIST') %}
<button type="submit" class="btn btn-success" name="btn_create_and_list"><i class="fa fa-save"></i> <i class="fa fa-list" aria-hidden="true"></i> {{ 'btn_create_and_return_to_list'|trans({}, 'SonataAdminBundle') }}</button>
{% endif %}
<button class="btn btn-success" type="submit" name="btn_create_and_create"><i class="fa fa-plus-circle" aria-hidden="true"></i> {{ 'btn_create_and_create_a_new_one'|trans({}, 'SonataAdminBundle') }}</button>
{% endif %}
{% endif %}
{% endblock %}
</div>
{% endblock formactions %}
</form>
{% endif%}
{{ sonata_block_render_event('sonata.admin.edit.form.bottom', { 'admin': admin, 'object': object }) }}
{% endblock %}
{% endblock %}
Ho
Create a template that extends base_edit.html.twig:
{% extends 'SonataAdminBundle:CRUD:base_edit.html.twig' %}
{% block form %}
{# your custom code #}
{{ parent() }}
{% endblock %}
Then to make sure only the admin you want uses that template pass it in the definition of your admin service with a setTemplate call:
librinfo_crm.admin.contact:
class: Librinfo\CRMBundle\Admin\ContactAdmin
arguments: [~, Librinfo\CRMBundle\Entity\Contact, SonataAdminBundle:CRUD]
tags:
- name: sonata.admin
manager_type: orm
group: Customers Relationship Management
label: librinfo.crm.contact_admin.label
label_translator_strategy: blast_core.label.strategy.librinfo
calls:
- [ setTemplate, [edit, LibrinfoCRMBundle:OrganismAdmin:edit.html.twig]]

Is it possible to extend the behavior of Symfony2 form_row()?

Is it possible to add a class in the div container when there's an error in that field? For example adding class has-error to the class attribute of the div container
{% block field_row %}
<div class="form_row has-error">
{{ form_label(form) }}
{{ form_errors(form) }}
{{ form_widget(form) }}
</div>
{% endblock field_row %}
{% block field_row %}
<div class="form_row{% if form_errors(form) %} has-error{% endif %}">
{{ form_label(form) }}
{{ form_errors(form) }}
{{ form_widget(form) }}
</div>
{% endblock field_row %}

Resources