forms - custom - symfony form label
Cómo personalizar el atributo de prototipo de datos en formularios Symfony 2 (11)
Esta publicación se centra en el uso de convenciones preexistentes dentro de la plantilla twig.
Al basar "Cómo insertar una colección de formularios" en el Cookbook de Symfony ( http://symfony.com/doc/master/cookbook/form/form_collections.html ), solo puede ingresar los datos de formulario html_escaped que desee en los datos -prototype (tal vez considerado un truco, pero funciona maravillosamente) y solo cambiarán las páginas que usan esa plantilla.
En el ejemplo, te dicen que pongas:
<ul class="tags" data-prototype="{{ form_widget(form.tags.vars.prototype)|e }}">
...
</ul>
Esto se puede reemplazar con éxito con algo como:
<table class="tags" data-prototype="<tr> <td><div><input type="text" id="task_tags__name__tagId" name="task[tags][__name__][taskId]" disabled="disabled" required="required" size="10" value="" /></div></td> <td><div><input type="text" id="task_tags__name__tagName" name="task[tags[__name__][tagName]" required="required" value="" /></div></td></tr>">
<tr>
<th>Id</th>
<th>Name</th>
</tr>
<tr>
...pre existing data here...
</tr>
</table>
Donde el atributo de tipo de datos de la tabla con la clase "etiquetas" anterior es la versión escapada html (y los saltos de línea eliminados aunque los espacios son correctos y obligatorios) de:
<tr>
<td><div><input type="text" id="task_tags__name__tagId" name="task[tags][__name__][taskId]" disabled="disabled" required="required" size="10" value="" /></div></td>
<td><div><input type="text" id="task_tags__name__tagName" name="task[tags[__name__][tagName]" required="required" value="" /></div></td>
</tr>
... pero también debe ajustar el javascript en el ejemplo para agregar elementos tr en lugar de li:
function addTagForm(collectionHolder, $newLinkTr) {
...
// Display the form in the page in an tr, before the "Add a question" link tr
var $newFormTr = $(''<tr></tr>'').append(newForm);
...
};
...
// setup an "add a tag" link
var $addTagLink = $(''<a href="#" class="add_tag_link">Add a tag</a>'');
var $newLinkTr = $(''<tr></tr>'').append($addTagLink);
...
Para mí, el siguiente paso es descubrir cómo definir el prototipo en un archivo externo al que de alguna manera puedo llamar en la plantilla twig para el prototipo de datos que funciona dinámicamente con el formulario. Algo como:
<table class="tags" data-prototype="{{somefunction(''App/Bundle/Views/Entity/TagsPrototypeInTable'')}}">
Entonces, si una de las otras publicaciones está describiendo esto y yo soy demasiado densa o si alguien sabe cómo hacerlo, ¡dígalo!
Hay un enlace a algo de gitHub de Francois, pero no vi ninguna explicación, así que creo que ese es probablemente el método más dinámico que obtendré en uno de estos días en el futuro cercano.
Paz, Steve
Actualizar:
También se pueden usar solo partes del prototipo:
data-prototype="<tr> <td>{{ form_row(form.tags.vars.prototype.tagId) | e }}</td> <td>{{ form_row(form.tags.vars.prototype.tagName) | e }}</td></tr>"
Donde el atributo de tipo de datos de la tabla con la clase "etiquetas" anterior es la versión escapada html (y los saltos de línea eliminados aunque los espacios son correctos y obligatorios) de:
<td>{{ form_row(form.tags.vars.prototype.tagId) | e }}</td>
<td>{{ form_row(form.tags.vars.prototype.tagName) | e }}</td>
(Utilicé http://www.htmlescape.net/htmlescape_tool.html .)
Symfony reemplazará la información entre el {{}} con un campo renderizado html_escaped (debido al "| e") cuando se procesa la página. De esta forma, cualquier personalización a nivel de campo no se pierde, sino! debe agregar y quitar campos manualmente al prototipo mientras lo hace con la entidad :)
Desde hace varios días, bloqueo un problema con Symfony 2 y formularios.
Obtuve una forma de entidades de sitios web. "Sitios web" es una colección de entidades del sitio web y cada sitio web contiene dos atributos: "tipo" y "url".
Si deseo agregar más de un sitio web en mi base de datos, puedo hacer clic en el enlace "Agregar otro sitio web", que agrega otra fila de sitio web a mi formulario. Entonces, cuando haces clic en el botón de enviar, puedes agregar uno o más sitios web de X al mismo tiempo.
Este proceso para agregar una fila utiliza el atributo de prototipo de datos, que puede generar la subforma del sitio web.
El problema es que personalizo mi formulario para tener una gran representación gráfica ... así:
<div class="informations_widget">{{ form_widget(website.type.code) }}</div>
<div class="informations_error">{{ form_errors(website.type) }}</div>
<div class="informations_widget">{{ form_widget(website.url) }}</div>
<div class="informations_error">{{ form_errors(website.url) }}</div>
Pero el prototipo de datos no se preocupa por esta personalización, con etiquetas y propiedades HTML y CSS. Guardo la representación de Symfony:
<div>
<label class=" required">$$name$$</label>
<div id="jobcast_profilebundle_websitestype_websites_$$name$$">
<div>
<label class=" required">Type</label>
<div id="jobcast_profilebundle_websitestype_websites_$$name$$_type">
<div>
<label for="jobcast_profilebundle_websitestype_websites_$$name$$_type_code" class=" required">label</label>
<select id="jobcast_profilebundle_websitestype_websites_$$name$$_type_code" name="jobcast_profilebundle_websitestype[websites][$$name$$][type][code]" required="required">
<option value="WEB-OTHER">Autre</option>
<option value="WEB-RSS">Flux RSS</option>
...
</select>
</div>
</div>
</div>
<div>
<label for="jobcast_profilebundle_websitestype_websites_$$name$$_url" class=" required">Adresse</label>
<input type="url" id="jobcast_profilebundle_websitestype_websites_$$name$$_url" name="jobcast_profilebundle_websitestype[websites][$$name$$][url]" required="required" value="" />
</div>
</div>
</div>
¿Alguien tiene una idea para hacer ese truco?
Me encontré con un problema similar recientemente. Así es cómo puede anular el prototipo de colección sin tener que establecerlo explícitamente en el html:
{% set customPrototype %}
{% filter escape %}
{% include ''AcmeBundle:Controller:customCollectionPrototype.html.twig'' with { ''form'': form.collection.vars.prototype } %}
{% endfilter %}
{% endset %}
{{ form_label(form.collection) }}
{{ form_widget(form.collection, { ''attr'': { ''data-prototype'': customPrototype } }) }}
Puedes hacer lo que quieras luego en tu ramita personalizada. Por ejemplo:
<div data-form-collection="item" data-form-collection-index="__name__" class="collection-item">
<div class="collection-box col-sm-10 col-sm-offset-2 padding-top-20">
<div class="row form-horizontal form-group">
<div class="col-sm-4">
{{ form_label(form.field0) }}
{{ form_widget(form.field0) }}
</div>
<div class="col-sm-3">
{{ form_label(form.field1) }}
{{ form_widget(form.field1) }}
</div>
<label class="col-sm-3 control-label text-right">
<button data-form-collection="delete" class="btn btn-danger">
<i class="fa fa-times collection-button-remove"></i>{{ ''form.collection.delete''|trans }}
</button>
</label>
</div>
</div>
Útil cuando solo tiene que hacerlo en lugares específicos y no necesita una anulación global aplicable a todas las colecciones.
Para personalizar el prototipo VS de elementos de colección diferentes, puede anular collection_widget de la siguiente manera:
{%- block collection_widget -%}
{% if prototype is defined %}
{%- set attr = attr|merge({''data-prototype'': form_row(prototype, {''inPrototype'': true} ) }) -%}
{% endif %}
{{- block(''form_widget'') -}}
{%- endblock collection_widget -%}
Y luego en tu entrada personalizada:
{% block _myCollection_entry_row %}
{% if(inPrototype is defined) %}
{# Something special only for prototype here #}
{% endif %}
{% endblock %}
Probablemente lo haya descubierto desde entonces, pero esta es la solución para otros.
Cree una nueva plantilla y copie / pegue este código en ella: https://gist.github.com/1294186
Luego, en la plantilla que contiene el formulario que desea personalizar, aplíquelo en su formulario haciendo esto:
{% form_theme form ''YourBundle:Deal:Theme/_field-prototype.html.twig'' %}
Sé que esta pregunta es bastante antigua, pero tuve el mismo problema y así es como lo resolví. Estoy usando una macro
ramita para lograr esto. Las macros son como funciones, puedes renderizarlas con diferentes argumentos.
{% macro information_prototype(website) %}
<div class="informations_widget">{{ form_widget(website.type.code) }}</div>
<div class="informations_error">{{ form_errors(website.type) }}</div>
<div class="informations_widget">{{ form_widget(website.url) }}</div>
<div class="informations_error">{{ form_errors(website.url) }}</div>
{% endmacro %}
ahora puedes renderizar esta macro donde quieras. Tenga en cuenta que information_prototype()
es solo el nombre de la macro, puede asignarle el nombre que desee. Si desea usar la macro para representar los elementos y el prototipo del mismo modo, haga algo como esto:
<div class="collection" data-prototype="{{ _self.information_prototype(form.websites.vars.prototype)|e }}">
{% for website in form.websites %}
{{ _self.information_prototype(website) }}
{% endfor %}
<button class="add-collection">Add Information</button>
</div>
form.websites.vars.prototype
contiene los datos prototipo del formulario con el prototype_name
que especificó. Use _self.+macroname
si desea usar la macro en la misma plantilla.
Puede encontrar más información sobre macros en la documentación de Twig
Sé que la respuesta es muy tarde pero quizás sea útil para los visitantes.
en su archivo de tema puede simplemente usar un bloque para representar cada entrada de colección de widget de sitios web de la siguiente manera:
{% block _jobcast_profilebundle_websitestype_websites_entry_widget %}
<div class="informations_widget">{{ form_widget(form.type.code) }}</div>
<div class="informations_error">{{ form_errors(form.type) }}</div>
<div class="informations_widget">{{ form_widget(form.url) }}</div>
<div class="informations_error">{{ form_errors(form.url) }}</div>
{% endblock %}
también crea un bloque de tema para tu fila de widget de colección de la siguiente manera:
{% block _quiz_question_answers_row %}
{% if prototype is defined %}
{%- set attr = attr | merge({''data-prototype'': form_row(prototype) }) -%}
{% endif %}
{{ form_errors(form) }}
{% for child in form %}
{{ form_row(child) }}
{% endfor %}
{% endblock %}
ahora el prototipo y la entrada de la colección representada serán los mismos.
Se aplicará una tematización de forma amplia a la aplicación del prototipo. Consulte Realización de personalizaciones de toda la aplicación
Si no necesita definir una plantilla en todo el sistema, simplemente configure una plantilla en su plantilla de ramita y solicite a ramita que la use.
{# using the profiler, you can find the block widget tested by twig #}
{% block my_block_widget %}
<div >
<p>My template for collection</p>
<div >
{{ form_row(form.field1)}}
</div>
<div>
{{ form_row(form.field2)}}
</div>
</div>
{% endblock %}
{% form_theme form.my_collection _self %}
<button data-form-prototype="{{ form_widget(form.my_collection.vars.prototype) )|e }}" >Add a new entry</button>
Tuve un problema similar. Es posible que tenga que modificar esto para que funcione en su caso, pero a alguien le puede resultar útil.
Crea un nuevo archivo de plantilla para mantener tu forma personalizada ''tema''
./src/Company/TestBundle/Resources/views/Forms/fields.html.twig
Normalmente, puede usar la función form_row para mostrar la etiqueta, el error y el widget de un campo. Pero en mi caso solo quería mostrar el widget. Como dices, el uso de la función de prototipo de datos también mostraría la etiqueta, por lo que en nuestro nuevo campo.html.twig escribe tu código personalizado para ver cómo quieres que se vea el campo:
{% block form_row %}
{% spaceless %}
{{ form_widget(form) }}
{% endspaceless %}
{% endblock form_row %}
Eliminé el contenedor div, y la etiqueta y el error, y simplemente abandoné el widget.
Ahora, en el archivo twig que muestra el formulario, simplemente agréguelo después de {% extends ...%}
{% form_theme form ''CompanyTestBundle:Form:fields.html.twig'' %}
Y ahora el form_widget (form.yourVariable.var.prototype) solo mostrará el campo y nada más.
Un poco viejo, pero aquí hay una solución mortalmente simple.
La idea es simplemente renderizar los elementos de la colección a través de una plantilla Twig, para que tenga la capacidad completa de personalizar el prototipo que se colocará en su etiqueta data-prototype="..."
. Como si fuera una forma normal y habitual.
En yourMainForm.html.twig:
<div id="collectionContainer"
data-prototype="
{% filter escape %}
{{ include(''MyBundle:MyViewsDirectory:prototype.html.twig'', { ''form'': form.myForm.vars.prototype }) }}
{% endfilter %}">
</div>
Y en MyBundle: MyViewsDirectory: prototype.html.twig:
<div>
<!-- customize as you wish -->
{{ form_label(form.field1) }}
{{ form_widget(form.field1) }}
{{ form_label(form.field2) }}
{{ form_widget(form.field2) }}
</div>
Crédito: adaptado de https://gist.github.com/tobalgists/4032213
Aquí hay un código de muestra para un prototipo de datos personalizado:
{{ form_widget(form.emails.get(''prototype'')) | e }}
donde los emails
- su colección.