[TwigBridge] Add form templates for Bootstrap 5
This commit is contained in:
parent
926f87ff51
commit
d52d0969ab
@ -2,10 +2,11 @@ CHANGELOG
|
||||
=========
|
||||
|
||||
5.3
|
||||
-----
|
||||
---
|
||||
|
||||
* Add a new `markAsPublic` method on `NotificationEmail` to change the `importance` context option to null after creation
|
||||
* Add a new `fragment_uri()` helper to generate the URI of a fragment
|
||||
* Add support of Bootstrap 5 for form theming
|
||||
|
||||
5.3.0
|
||||
-----
|
||||
|
@ -54,6 +54,11 @@
|
||||
{%- endif -%}
|
||||
{%- endblock radio_widget %}
|
||||
|
||||
{% block choice_widget_collapsed -%}
|
||||
{%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-control')|trim}) -%}
|
||||
{{- parent() -}}
|
||||
{%- endblock choice_widget_collapsed %}
|
||||
|
||||
{# Labels #}
|
||||
|
||||
{% block form_label -%}
|
||||
|
@ -202,6 +202,11 @@
|
||||
{%- endif -%}
|
||||
{%- endblock radio_widget %}
|
||||
|
||||
{% block choice_widget_collapsed -%}
|
||||
{%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-control')|trim}) -%}
|
||||
{{- parent() -}}
|
||||
{%- endblock choice_widget_collapsed %}
|
||||
|
||||
{% block choice_widget_expanded -%}
|
||||
<div {{ block('widget_container_attributes') }}>
|
||||
{%- for child in form %}
|
||||
|
@ -0,0 +1,130 @@
|
||||
{% use "bootstrap_5_layout.html.twig" %}
|
||||
|
||||
{# Labels #}
|
||||
|
||||
{% block form_label -%}
|
||||
{%- if label is same as(false) -%}
|
||||
<div class="{{ block('form_label_class') }}"></div>
|
||||
{%- else -%}
|
||||
{%- set row_class = row_class|default(row_attr.class|default('')) -%}
|
||||
{%- if 'form-floating' not in row_class and 'input-group' not in row_class -%}
|
||||
{%- if expanded is not defined or not expanded -%}
|
||||
{%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' col-form-label')|trim}) -%}
|
||||
{%- endif -%}
|
||||
{%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' ' ~ block('form_label_class'))|trim}) -%}
|
||||
{%- endif -%}
|
||||
{{- parent() -}}
|
||||
{%- endif -%}
|
||||
{%- endblock form_label %}
|
||||
|
||||
{% block form_label_class -%}
|
||||
col-sm-2
|
||||
{%- endblock form_label_class %}
|
||||
|
||||
{# Rows #}
|
||||
|
||||
{% block form_row -%}
|
||||
{%- if expanded is defined and expanded -%}
|
||||
{{ block('fieldset_form_row') }}
|
||||
{%- else -%}
|
||||
{%- set widget_attr = {} -%}
|
||||
{%- if help is not empty -%}
|
||||
{%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%}
|
||||
{%- endif -%}
|
||||
{%- set row_class = row_class|default(row_attr.class|default('mb-3')) -%}
|
||||
{%- set is_form_floating = is_form_floating|default('form-floating' in row_class) -%}
|
||||
{%- set is_input_group = is_input_group|default('input-group' in row_class) -%}
|
||||
{#- Remove behavior class from the main container -#}
|
||||
{%- set row_class = row_class|replace({'form-floating': '', 'input-group': ''}) -%}
|
||||
<div{% with {attr: row_attr|merge({class: (row_class ~ ' row' ~ ((not compound or force_error|default(false)) and not valid ? ' is-invalid'))|trim})} %}{{ block('attributes') }}{% endwith %}>
|
||||
{%- if is_form_floating or is_input_group -%}
|
||||
<div class="{{ block('form_label_class') }}"></div>
|
||||
<div class="{{ block('form_group_class') }}">
|
||||
{%- if is_form_floating -%}
|
||||
<div class="form-floating">
|
||||
{{- form_widget(form, widget_attr) -}}
|
||||
{{- form_label(form) -}}
|
||||
</div>
|
||||
{%- elseif is_input_group -%}
|
||||
<div class="input-group">
|
||||
{{- form_label(form) -}}
|
||||
{{- form_widget(form, widget_attr) -}}
|
||||
{#- Hack to properly display help with input group -#}
|
||||
{{- form_help(form) -}}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- if not is_input_group -%}
|
||||
{{- form_help(form) -}}
|
||||
{%- endif -%}
|
||||
{{- form_errors(form) -}}
|
||||
</div>
|
||||
{%- else -%}
|
||||
{{- form_label(form) -}}
|
||||
<div class="{{ block('form_group_class') }}">
|
||||
{{- form_widget(form, widget_attr) -}}
|
||||
{{- form_help(form) -}}
|
||||
{{- form_errors(form) -}}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{##}</div>
|
||||
{%- endif -%}
|
||||
{%- endblock form_row %}
|
||||
|
||||
{% block fieldset_form_row -%}
|
||||
{%- set widget_attr = {} -%}
|
||||
{%- if help is not empty -%}
|
||||
{%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%}
|
||||
{%- endif -%}
|
||||
<fieldset{% with {attr: row_attr|merge({class: row_attr.class|default('mb-3')|trim})} %}{{ block('attributes') }}{% endwith %}>
|
||||
<div class="row{% if (not compound or force_error|default(false)) and not valid %} is-invalid{% endif %}">
|
||||
{{- form_label(form) -}}
|
||||
<div class="{{ block('form_group_class') }}">
|
||||
{{- form_widget(form, widget_attr) -}}
|
||||
{{- form_help(form) -}}
|
||||
{{- form_errors(form) -}}
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
{%- endblock fieldset_form_row %}
|
||||
|
||||
{% block submit_row -%}
|
||||
<div{% with {attr: row_attr|merge({class: (row_attr.class|default('mb-3') ~ ' row')|trim})} %}{{ block('attributes') }}{% endwith %}>{#--#}
|
||||
<div class="{{ block('form_label_class') }}"></div>{#--#}
|
||||
<div class="{{ block('form_group_class') }}">
|
||||
{{- form_widget(form) -}}
|
||||
</div>{#--#}
|
||||
</div>
|
||||
{%- endblock submit_row %}
|
||||
|
||||
{% block reset_row -%}
|
||||
<div{% with {attr: row_attr|merge({class: (row_attr.class|default('mb-3') ~ ' row')|trim})} %}{{ block('attributes') }}{% endwith %}>{#--#}
|
||||
<div class="{{ block('form_label_class') }}"></div>{#--#}
|
||||
<div class="{{ block('form_group_class') }}">
|
||||
{{- form_widget(form) -}}
|
||||
</div>{#--#}
|
||||
</div>
|
||||
{%- endblock reset_row %}
|
||||
|
||||
{% block button_row -%}
|
||||
<div{% with {attr: row_attr|merge({class: (row_attr.class|default('mb-3') ~ ' row')|trim})} %}{{ block('attributes') }}{% endwith %}>{#--#}
|
||||
<div class="{{ block('form_label_class') }}"></div>{#--#}
|
||||
<div class="{{ block('form_group_class') }}">
|
||||
{{- form_widget(form) -}}
|
||||
</div>{#--#}
|
||||
</div>
|
||||
{%- endblock button_row %}
|
||||
|
||||
{% block checkbox_row -%}
|
||||
<div{% with {attr: row_attr|merge({class: (row_attr.class|default('mb-3') ~ ' row')|trim})} %}{{ block('attributes') }}{% endwith %}>{#--#}
|
||||
<div class="{{ block('form_label_class') }}"></div>{#--#}
|
||||
<div class="{{ block('form_group_class') }}">
|
||||
{{- form_widget(form) -}}
|
||||
{{- form_help(form) -}}
|
||||
{{- form_errors(form) -}}
|
||||
</div>{#--#}
|
||||
</div>
|
||||
{%- endblock checkbox_row %}
|
||||
|
||||
{% block form_group_class -%}
|
||||
col-sm-10
|
||||
{%- endblock form_group_class %}
|
@ -0,0 +1,374 @@
|
||||
{% use "bootstrap_base_layout.html.twig" %}
|
||||
|
||||
{# Widgets #}
|
||||
|
||||
{% block money_widget -%}
|
||||
{%- set prepend = not (money_pattern starts with '{{') -%}
|
||||
{%- set append = not (money_pattern ends with '}}') -%}
|
||||
{%- if prepend or append -%}
|
||||
<div class="input-group{{ group_class|default('') }}">
|
||||
{%- if prepend -%}
|
||||
<span class="input-group-text">{{ money_pattern|form_encode_currency }}</span>
|
||||
{%- endif -%}
|
||||
{{- block('form_widget_simple') -}}
|
||||
{%- if append -%}
|
||||
<span class="input-group-text">{{ money_pattern|form_encode_currency }}</span>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
{%- else -%}
|
||||
{{- block('form_widget_simple') -}}
|
||||
{%- endif -%}
|
||||
{%- endblock money_widget %}
|
||||
|
||||
{% block date_widget -%}
|
||||
{%- if widget == 'single_text' -%}
|
||||
{{- block('form_widget_simple') -}}
|
||||
{%- else -%}
|
||||
{% if not valid %}
|
||||
{% set attr = attr|merge({class: (attr.class|default('') ~ ' is-invalid')|trim}) -%}
|
||||
{% set valid = true %}
|
||||
{% endif %}
|
||||
{%- if datetime is not defined or not datetime -%}
|
||||
<div {{ block('widget_container_attributes') -}}>
|
||||
{%- endif %}
|
||||
{%- if label is not same as(false) -%}
|
||||
<div class="visually-hidden">
|
||||
{{- form_label(form.year) -}}
|
||||
{{- form_label(form.month) -}}
|
||||
{{- form_label(form.day) -}}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
<div class="input-group">
|
||||
{{- date_pattern|replace({
|
||||
'{{ year }}': form_widget(form.year),
|
||||
'{{ month }}': form_widget(form.month),
|
||||
'{{ day }}': form_widget(form.day),
|
||||
})|raw -}}
|
||||
</div>
|
||||
{%- if datetime is not defined or not datetime -%}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{%- endblock date_widget %}
|
||||
|
||||
{% block time_widget -%}
|
||||
{%- if widget == 'single_text' -%}
|
||||
{{- block('form_widget_simple') -}}
|
||||
{%- else -%}
|
||||
{% if not valid %}
|
||||
{% set attr = attr|merge({class: (attr.class|default('') ~ ' is-invalid')|trim}) -%}
|
||||
{% set valid = true %}
|
||||
{% endif %}
|
||||
{%- if datetime is not defined or false == datetime -%}
|
||||
<div {{ block('widget_container_attributes') -}}>
|
||||
{%- endif -%}
|
||||
{%- if label is not same as(false) -%}
|
||||
<div class="visually-hidden">
|
||||
{{- form_label(form.hour) -}}
|
||||
{%- if with_minutes -%}{{ form_label(form.minute) }}{%- endif -%}
|
||||
{%- if with_seconds -%}{{ form_label(form.second) }}{%- endif -%}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{% if with_minutes or with_seconds %}
|
||||
<div class="input-group">
|
||||
{% endif %}
|
||||
{{- form_widget(form.hour) -}}
|
||||
{%- if with_minutes -%}
|
||||
<span class="input-group-text">:</span>
|
||||
{{- form_widget(form.minute) -}}
|
||||
{%- endif -%}
|
||||
{%- if with_seconds -%}
|
||||
<span class="input-group-text">:</span>
|
||||
{{- form_widget(form.second) -}}
|
||||
{%- endif -%}
|
||||
{% if with_minutes or with_seconds %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{%- if datetime is not defined or false == datetime -%}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{%- endblock time_widget %}
|
||||
|
||||
{% block datetime_widget -%}
|
||||
{%- if widget == 'single_text' -%}
|
||||
{{- block('form_widget_simple') -}}
|
||||
{%- else -%}
|
||||
{% if not valid %}
|
||||
{% set attr = attr|merge({class: (attr.class|default('') ~ ' is-invalid')|trim}) -%}
|
||||
{% set valid = true %}
|
||||
{% endif %}
|
||||
<div {{ block('widget_container_attributes') }}>
|
||||
{{- form_widget(form.date, { datetime: true } ) -}}
|
||||
{{- form_errors(form.date) -}}
|
||||
{{- form_widget(form.time, { datetime: true } ) -}}
|
||||
{{- form_errors(form.time) -}}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- endblock datetime_widget %}
|
||||
|
||||
{% block dateinterval_widget -%}
|
||||
{%- if widget == 'single_text' -%}
|
||||
{{- block('form_widget_simple') -}}
|
||||
{%- else -%}
|
||||
{% if not valid %}
|
||||
{% set attr = attr|merge({class: (attr.class|default('') ~ ' is-invalid')|trim}) -%}
|
||||
{% set valid = true %}
|
||||
{% endif %}
|
||||
<div {{ block('widget_container_attributes') }}>
|
||||
{%- if with_years -%}
|
||||
<div class="col-auto mb-3">
|
||||
{{ form_label(form.years) }}
|
||||
{{ form_widget(form.years) }}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- if with_months -%}
|
||||
<div class="col-auto mb-3">
|
||||
{{ form_label(form.months) }}
|
||||
{{ form_widget(form.months) }}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- if with_weeks -%}
|
||||
<div class="col-auto mb-3">
|
||||
{{ form_label(form.weeks) }}
|
||||
{{ form_widget(form.weeks) }}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- if with_days -%}
|
||||
<div class="col-auto mb-3">
|
||||
{{ form_label(form.days) }}
|
||||
{{ form_widget(form.days) }}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- if with_hours -%}
|
||||
<div class="col-auto mb-3">
|
||||
{{ form_label(form.hours) }}
|
||||
{{ form_widget(form.hours) }}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- if with_minutes -%}
|
||||
<div class="col-auto mb-3">
|
||||
{{ form_label(form.minutes) }}
|
||||
{{ form_widget(form.minutes) }}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- if with_seconds -%}
|
||||
<div class="col-auto mb-3">
|
||||
{{ form_label(form.seconds) }}
|
||||
{{ form_widget(form.seconds) }}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- if with_invert %}{{ form_widget(form.invert) }}{% endif -%}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- endblock dateinterval_widget %}
|
||||
|
||||
{% block percent_widget -%}
|
||||
{%- if symbol -%}
|
||||
<div class="input-group">
|
||||
{{- block('form_widget_simple') -}}
|
||||
<span class="input-group-text">{{ symbol|default('%') }}</span>
|
||||
</div>
|
||||
{%- else -%}
|
||||
{{- block('form_widget_simple') -}}
|
||||
{%- endif -%}
|
||||
{%- endblock percent_widget %}
|
||||
|
||||
{% block form_widget_simple -%}
|
||||
{%- if type is not defined or type != 'hidden' %}
|
||||
{%- set widget_class = ' form-control' %}
|
||||
{%- if type|default('') == 'color' -%}
|
||||
{%- set widget_class = widget_class ~ ' form-control-color' -%}
|
||||
{%- elseif type|default('') == 'range' -%}
|
||||
{%- set widget_class = ' form-range' -%}
|
||||
{%- endif -%}
|
||||
{%- set attr = attr|merge({class: (attr.class|default('') ~ widget_class)|trim}) -%}
|
||||
{% endif -%}
|
||||
{%- if type is defined and type in ['range', 'color'] %}
|
||||
{# Attribute "required" is not supported #}
|
||||
{% set required = false %}
|
||||
{% endif -%}
|
||||
{{- parent() -}}
|
||||
{%- endblock form_widget_simple %}
|
||||
|
||||
{%- block widget_attributes -%}
|
||||
{%- if not valid %}
|
||||
{% set attr = attr|merge({class: (attr.class|default('') ~ ' is-invalid')|trim}) %}
|
||||
{% endif -%}
|
||||
{{ parent() }}
|
||||
{%- endblock widget_attributes -%}
|
||||
|
||||
{%- block button_widget -%}
|
||||
{%- set attr = attr|merge({class: (attr.class|default('btn-secondary') ~ ' btn')|trim}) -%}
|
||||
{{- parent() -}}
|
||||
{%- endblock button_widget %}
|
||||
|
||||
{%- block submit_widget -%}
|
||||
{%- set attr = attr|merge({class: (attr.class|default('btn-primary'))|trim}) -%}
|
||||
{{- parent() -}}
|
||||
{%- endblock submit_widget %}
|
||||
|
||||
{%- block checkbox_widget -%}
|
||||
{%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-check-input')|trim}) -%}
|
||||
{%- set parent_label_class = parent_label_class|default(label_attr.class|default('')) -%}
|
||||
{%- set row_class = 'form-check' -%}
|
||||
{%- if 'checkbox-inline' in parent_label_class %}
|
||||
{% set row_class = row_class ~ ' form-check-inline' %}
|
||||
{% endif -%}
|
||||
{%- if 'checkbox-switch' in parent_label_class %}
|
||||
{% set row_class = row_class ~ ' form-switch' %}
|
||||
{% endif -%}
|
||||
<div class="{{ row_class }}">
|
||||
{{- form_label(form, null, { widget: parent() }) -}}
|
||||
</div>
|
||||
{%- endblock checkbox_widget %}
|
||||
|
||||
{%- block radio_widget -%}
|
||||
{%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-check-input')|trim}) -%}
|
||||
{%- set parent_label_class = parent_label_class|default(label_attr.class|default('')) -%}
|
||||
{%- set row_class = 'form-check' -%}
|
||||
{%- if 'radio-inline' in parent_label_class -%}
|
||||
{%- set row_class = row_class ~ ' form-check-inline' -%}
|
||||
{%- endif -%}
|
||||
<div class="{{ row_class }}">
|
||||
{{- form_label(form, null, { widget: parent() }) -}}
|
||||
</div>
|
||||
{%- endblock radio_widget %}
|
||||
|
||||
{%- block choice_widget_collapsed -%}
|
||||
{%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-select')|trim}) -%}
|
||||
{{- parent() -}}
|
||||
{%- endblock choice_widget_collapsed -%}
|
||||
|
||||
{%- block choice_widget_expanded -%}
|
||||
<div {{ block('widget_container_attributes') }}>
|
||||
{%- for child in form %}
|
||||
{{- form_widget(child, {
|
||||
parent_label_class: label_attr.class|default(''),
|
||||
translation_domain: choice_translation_domain,
|
||||
valid: valid,
|
||||
}) -}}
|
||||
{% endfor -%}
|
||||
</div>
|
||||
{%- endblock choice_widget_expanded %}
|
||||
|
||||
{# Labels #}
|
||||
|
||||
{%- block form_label -%}
|
||||
{% if label is not same as(false) -%}
|
||||
{%- set parent_label_class = parent_label_class|default(label_attr.class|default('')) -%}
|
||||
{%- if compound is defined and compound -%}
|
||||
{%- set element = 'legend' -%}
|
||||
{%- if 'col-form-label' not in parent_label_class -%}
|
||||
{%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' col-form-label' )|trim}) -%}
|
||||
{%- endif -%}
|
||||
{%- else -%}
|
||||
{%- set row_class = row_class|default(row_attr.class|default('')) -%}
|
||||
{%- set label_attr = label_attr|merge({for: id}) -%}
|
||||
{%- if 'col-form-label' not in parent_label_class -%}
|
||||
{%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ('input-group' in row_class ? ' input-group-text' : ' form-label') )|trim}) -%}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{{- parent() -}}
|
||||
{%- endblock form_label %}
|
||||
|
||||
{%- block checkbox_radio_label -%}
|
||||
{#- Do not display the label if widget is not defined in order to prevent double label rendering -#}
|
||||
{%- if widget is defined -%}
|
||||
{%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' form-check-label')|trim}) -%}
|
||||
{%- if not compound -%}
|
||||
{% set label_attr = label_attr|merge({'for': id}) %}
|
||||
{%- endif -%}
|
||||
{%- if required -%}
|
||||
{%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' required')|trim}) -%}
|
||||
{%- endif -%}
|
||||
{%- if parent_label_class is defined -%}
|
||||
{%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' ' ~ parent_label_class)|replace({'checkbox-inline': '', 'radio-inline': ''})|trim}) -%}
|
||||
{%- endif -%}
|
||||
{%- if label is not same as(false) and 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 -%}
|
||||
|
||||
{{ widget|raw }}
|
||||
<label{% with { attr: label_attr } %}{{ block('attributes') }}{% endwith %}>
|
||||
{%- if label is not same as(false) -%}
|
||||
{%- if translation_domain is same as(false) -%}
|
||||
{%- if label_html is same as(false) -%}
|
||||
{{- label -}}
|
||||
{%- else -%}
|
||||
{{- label|raw -}}
|
||||
{%- endif -%}
|
||||
{%- else -%}
|
||||
{%- if label_html is same as(false) -%}
|
||||
{{- label|trans(label_translation_parameters, translation_domain) -}}
|
||||
{%- else -%}
|
||||
{{- label|trans(label_translation_parameters, translation_domain)|raw -}}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
</label>
|
||||
{%- endif -%}
|
||||
{%- endblock checkbox_radio_label %}
|
||||
|
||||
{# Rows #}
|
||||
|
||||
{%- block form_row -%}
|
||||
{%- if compound is defined and compound -%}
|
||||
{%- set element = 'fieldset' -%}
|
||||
{%- endif -%}
|
||||
{%- set widget_attr = {} -%}
|
||||
{%- if help is not empty -%}
|
||||
{%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%}
|
||||
{%- endif -%}
|
||||
{%- set row_class = row_class|default(row_attr.class|default('mb-3')|trim) -%}
|
||||
<{{ element|default('div') }}{% with {attr: row_attr|merge({class: row_class})} %}{{ block('attributes') }}{% endwith %}>
|
||||
{%- if 'form-floating' in row_class -%}
|
||||
{{- form_widget(form, widget_attr) -}}
|
||||
{{- form_label(form) -}}
|
||||
{%- else -%}
|
||||
{{- form_label(form) -}}
|
||||
{{- form_widget(form, widget_attr) -}}
|
||||
{%- endif -%}
|
||||
{{- form_help(form) -}}
|
||||
{{- form_errors(form) -}}
|
||||
</{{ element|default('div') }}>
|
||||
{%- endblock form_row %}
|
||||
|
||||
{%- block button_row -%}
|
||||
<div{% with {attr: row_attr|merge({class: row_attr.class|default('mb-3')|trim})} %}{{ block('attributes') }}{% endwith %}>
|
||||
{{- form_widget(form) -}}
|
||||
</div>
|
||||
{%- endblock button_row %}
|
||||
|
||||
{# Errors #}
|
||||
|
||||
{%- block form_errors -%}
|
||||
{%- if errors|length > 0 -%}
|
||||
{%- for error in errors -%}
|
||||
<div class="invalid-feedback d-block">{{ error.message }}</div>
|
||||
{%- endfor -%}
|
||||
{%- endif %}
|
||||
{%- endblock form_errors %}
|
||||
|
||||
{# Help #}
|
||||
|
||||
{%- block form_help -%}
|
||||
{% set row_class = row_attr.class|default('') %}
|
||||
{% set help_class = ' form-text' %}
|
||||
{% if 'input-group' in row_class %}
|
||||
{#- Hack to properly display help with input group -#}
|
||||
{% set help_class = ' input-group-text' %}
|
||||
{% endif %}
|
||||
{%- if help is not empty -%}
|
||||
{%- set help_attr = help_attr|merge({class: (help_attr.class|default('') ~ help_class ~ ' mb-0')|trim}) -%}
|
||||
{%- endif -%}
|
||||
{{- parent() -}}
|
||||
{%- endblock form_help %}
|
@ -143,11 +143,6 @@
|
||||
{%- endif -%}
|
||||
{%- endblock dateinterval_widget -%}
|
||||
|
||||
{% block choice_widget_collapsed -%}
|
||||
{%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-control')|trim}) -%}
|
||||
{{- parent() -}}
|
||||
{%- endblock choice_widget_collapsed %}
|
||||
|
||||
{% block choice_widget_expanded -%}
|
||||
{%- if '-inline' in label_attr.class|default('') -%}
|
||||
{%- for child in form %}
|
||||
|
@ -0,0 +1,353 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Bridge\Twig\Tests\Extension;
|
||||
|
||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\DateType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\FileType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\RadioType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormError;
|
||||
|
||||
/**
|
||||
* Abstract class providing test cases for the Bootstrap 5 horizontal Twig form theme.
|
||||
*
|
||||
* @author Romain Monteil <monteil.romain@gmail.com>
|
||||
*/
|
||||
abstract class AbstractBootstrap5HorizontalLayoutTest extends AbstractBootstrap5LayoutTest
|
||||
{
|
||||
public function testRow()
|
||||
{
|
||||
$form = $this->factory->createNamed('name', TextType::class);
|
||||
$form->addError(new FormError('[trans]Error![/trans]'));
|
||||
$html = $this->renderRow($form->createView());
|
||||
|
||||
$this->assertMatchesXpath($html,
|
||||
'/div
|
||||
[@class="mb-3 row"]
|
||||
[
|
||||
./label
|
||||
[@for="name"]
|
||||
[@class="col-form-label col-sm-2 required"]
|
||||
/following-sibling::div
|
||||
[@class="col-sm-10"]
|
||||
[
|
||||
./input[@id="name"]
|
||||
/following-sibling::div
|
||||
[@class="invalid-feedback d-block"]
|
||||
[.="[trans]Error![/trans]"]
|
||||
]
|
||||
[count(./div)=1]
|
||||
]
|
||||
'
|
||||
);
|
||||
}
|
||||
|
||||
public function testRowWithCustomClass()
|
||||
{
|
||||
$form = $this->factory->createNamed('name', TextType::class);
|
||||
$form->addError(new FormError('[trans]Error![/trans]'));
|
||||
$html = $this->renderRow($form->createView(), [
|
||||
'row_attr' => [
|
||||
'class' => 'mb-5',
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertMatchesXpath($html,
|
||||
'/div
|
||||
[@class="mb-5 row"]
|
||||
[
|
||||
./label
|
||||
[@for="name"]
|
||||
[@class="col-form-label col-sm-2 required"]
|
||||
/following-sibling::div
|
||||
[@class="col-sm-10"]
|
||||
[
|
||||
./input[@id="name"]
|
||||
/following-sibling::div
|
||||
[@class="invalid-feedback d-block"]
|
||||
[.="[trans]Error![/trans]"]
|
||||
]
|
||||
[count(./div)=1]
|
||||
]
|
||||
'
|
||||
);
|
||||
}
|
||||
|
||||
public function testLabelOnForm()
|
||||
{
|
||||
$form = $this->factory->createNamed('name', DateType::class);
|
||||
$view = $form->createView();
|
||||
$this->renderWidget($view, ['label' => 'foo']);
|
||||
$html = $this->renderLabel($view);
|
||||
|
||||
$this->assertMatchesXpath($html,
|
||||
'/legend
|
||||
[@class="col-form-label col-sm-2 required"]
|
||||
[.="[trans]Name[/trans]"]
|
||||
'
|
||||
);
|
||||
}
|
||||
|
||||
public function testLabelDoesNotRenderFieldAttributes()
|
||||
{
|
||||
$form = $this->factory->createNamed('name', TextType::class);
|
||||
$html = $this->renderLabel($form->createView(), null, [
|
||||
'attr' => [
|
||||
'class' => 'my&class',
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertMatchesXpath($html,
|
||||
'/label
|
||||
[@for="name"]
|
||||
[@class="col-form-label col-sm-2 required"]
|
||||
'
|
||||
);
|
||||
}
|
||||
|
||||
public function testLabelWithCustomAttributesPassedDirectly()
|
||||
{
|
||||
$form = $this->factory->createNamed('name', TextType::class);
|
||||
$html = $this->renderLabel($form->createView(), null, [
|
||||
'label_attr' => [
|
||||
'class' => 'my&class',
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertMatchesXpath($html,
|
||||
'/label
|
||||
[@for="name"]
|
||||
[@class="my&class col-form-label col-sm-2 required"]
|
||||
'
|
||||
);
|
||||
}
|
||||
|
||||
public function testLabelWithCustomTextAndCustomAttributesPassedDirectly()
|
||||
{
|
||||
$form = $this->factory->createNamed('name', TextType::class);
|
||||
$html = $this->renderLabel($form->createView(), 'Custom label', [
|
||||
'label_attr' => [
|
||||
'class' => 'my&class',
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertMatchesXpath($html,
|
||||
'/label
|
||||
[@for="name"]
|
||||
[@class="my&class col-form-label col-sm-2 required"]
|
||||
[.="[trans]Custom label[/trans]"]
|
||||
'
|
||||
);
|
||||
}
|
||||
|
||||
public function testLabelWithCustomTextAsOptionAndCustomAttributesPassedDirectly()
|
||||
{
|
||||
$form = $this->factory->createNamed('name', TextType::class, null, [
|
||||
'label' => 'Custom label',
|
||||
]);
|
||||
$html = $this->renderLabel($form->createView(), null, [
|
||||
'label_attr' => [
|
||||
'class' => 'my&class',
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertMatchesXpath($html,
|
||||
'/label
|
||||
[@for="name"]
|
||||
[@class="my&class col-form-label col-sm-2 required"]
|
||||
[.="[trans]Custom label[/trans]"]
|
||||
'
|
||||
);
|
||||
}
|
||||
|
||||
public function testLabelHtmlDefaultIsFalse()
|
||||
{
|
||||
$form = $this->factory->createNamed('name', TextType::class, null, [
|
||||
'label' => '<b>Bolded label</b>',
|
||||
]);
|
||||
|
||||
$html = $this->renderLabel($form->createView(), null, [
|
||||
'label_attr' => [
|
||||
'class' => 'my&class',
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertMatchesXpath($html, '/label[@for="name"][@class="my&class col-form-label col-sm-2 required"][.="[trans]<b>Bolded label</b>[/trans]"]');
|
||||
$this->assertMatchesXpath($html, '/label[@for="name"][@class="my&class col-form-label col-sm-2 required"]/b[.="Bolded label"]', 0);
|
||||
}
|
||||
|
||||
public function testLabelHtmlIsTrue()
|
||||
{
|
||||
$form = $this->factory->createNamed('name', TextType::class, null, [
|
||||
'label' => '<b>Bolded label</b>',
|
||||
'label_html' => true,
|
||||
]);
|
||||
|
||||
$html = $this->renderLabel($form->createView(), null, [
|
||||
'label_attr' => [
|
||||
'class' => 'my&class',
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertMatchesXpath($html, '/label[@for="name"][@class="my&class col-form-label col-sm-2 required"][.="[trans]<b>Bolded label</b>[/trans]"]', 0);
|
||||
$this->assertMatchesXpath($html, '/label[@for="name"][@class="my&class col-form-label col-sm-2 required"]/b[.="Bolded label"]');
|
||||
}
|
||||
|
||||
public function testLegendOnExpandedType()
|
||||
{
|
||||
$form = $this->factory->createNamed('name', ChoiceType::class, null, [
|
||||
'label' => 'Custom label',
|
||||
'expanded' => true,
|
||||
'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'],
|
||||
]);
|
||||
$view = $form->createView();
|
||||
$this->renderWidget($view);
|
||||
$html = $this->renderLabel($view);
|
||||
|
||||
$this->assertMatchesXpath($html,
|
||||
'/legend
|
||||
[@class="col-sm-2 col-form-label required"]
|
||||
[.="[trans]Custom label[/trans]"]
|
||||
'
|
||||
);
|
||||
}
|
||||
|
||||
public function testCheckboxRow()
|
||||
{
|
||||
$form = $this->factory->createNamed('name', CheckboxType::class);
|
||||
$view = $form->createView();
|
||||
$html = $this->renderRow($view, ['label' => 'foo']);
|
||||
|
||||
$this->assertMatchesXpath($html, '/div[@class="mb-3 row"]/div[@class="col-sm-2" or @class="col-sm-10"]', 2);
|
||||
}
|
||||
|
||||
public function testCheckboxRowWithHelp()
|
||||
{
|
||||
$form = $this->factory->createNamed('name', CheckboxType::class);
|
||||
$view = $form->createView();
|
||||
$html = $this->renderRow($view, ['label' => 'foo', 'help' => 'really helpful text']);
|
||||
|
||||
$this->assertMatchesXpath($html,
|
||||
'/div
|
||||
[@class="mb-3 row"]
|
||||
[
|
||||
./div[@class="col-sm-2" or @class="col-sm-10"]
|
||||
/following-sibling::div[@class="col-sm-2" or @class="col-sm-10"]
|
||||
[
|
||||
./p
|
||||
[@class="form-text mb-0 help-text"]
|
||||
[.="[trans]really helpful text[/trans]"]
|
||||
]
|
||||
]
|
||||
'
|
||||
);
|
||||
}
|
||||
|
||||
public function testRadioRowWithHelp()
|
||||
{
|
||||
$form = $this->factory->createNamed('name', RadioType::class, false);
|
||||
$html = $this->renderRow($form->createView(), ['label' => 'foo', 'help' => 'really helpful text']);
|
||||
|
||||
$this->assertMatchesXpath($html,
|
||||
'/div
|
||||
[@class="mb-3 row"]
|
||||
[
|
||||
./div[@class="col-sm-2" or @class="col-sm-10"]
|
||||
/following-sibling::div[@class="col-sm-2" or @class="col-sm-10"]
|
||||
[
|
||||
./p
|
||||
[@class="form-text mb-0 help-text"]
|
||||
[.="[trans]really helpful text[/trans]"]
|
||||
]
|
||||
]
|
||||
'
|
||||
);
|
||||
}
|
||||
|
||||
public function testFileWithGroup()
|
||||
{
|
||||
$form = $this->factory->createNamed('name', FileType::class);
|
||||
$html = $this->renderRow($form->createView(), [
|
||||
'id' => 'n/a',
|
||||
'attr' => [
|
||||
'class' => 'my&class',
|
||||
],
|
||||
'row_attr' => [
|
||||
'class' => 'input-group mb-3',
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertMatchesXpath($html,
|
||||
'/div
|
||||
[@class="mb-3 row"]
|
||||
[
|
||||
./div
|
||||
[@class="col-sm-2"]
|
||||
/following-sibling::div
|
||||
[@class="col-sm-10"]
|
||||
[
|
||||
./div
|
||||
[@class="input-group"]
|
||||
[
|
||||
./label
|
||||
[@class="input-group-text required"]
|
||||
[.="[trans]Name[/trans]"]
|
||||
/following-sibling::input
|
||||
[@type="file"]
|
||||
[@name="name"]
|
||||
[@class="my&class form-control"]
|
||||
]
|
||||
]
|
||||
]
|
||||
'
|
||||
);
|
||||
}
|
||||
|
||||
public function testFloatingLabel()
|
||||
{
|
||||
$form = $this->factory->createNamed('name', TextType::class, null, [
|
||||
'attr' => [
|
||||
'placeholder' => 'name',
|
||||
],
|
||||
'row_attr' => [
|
||||
'class' => 'form-floating mb-3',
|
||||
],
|
||||
]);
|
||||
|
||||
$html = $this->renderRow($form->createView());
|
||||
|
||||
$this->assertMatchesXpath($html,
|
||||
'/div
|
||||
[@class="mb-3 row"]
|
||||
[
|
||||
./div
|
||||
[@class="col-sm-2"]
|
||||
/following-sibling::div
|
||||
[@class="col-sm-10"]
|
||||
[
|
||||
./div
|
||||
[@class="form-floating"]
|
||||
[
|
||||
./input
|
||||
[@id="name"]
|
||||
[@placeholder="[trans]name[/trans]"]
|
||||
/following-sibling::label
|
||||
[@for="name"]
|
||||
]
|
||||
]
|
||||
]
|
||||
'
|
||||
);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Bridge\Twig\Tests\Extension;
|
||||
|
||||
use Symfony\Bridge\Twig\Extension\FormExtension;
|
||||
use Symfony\Bridge\Twig\Extension\TranslationExtension;
|
||||
use Symfony\Bridge\Twig\Form\TwigRendererEngine;
|
||||
use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubTranslator;
|
||||
use Symfony\Component\Form\FormRenderer;
|
||||
use Symfony\Component\Form\FormView;
|
||||
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
|
||||
use Twig\Environment;
|
||||
use Twig\Loader\FilesystemLoader;
|
||||
|
||||
/**
|
||||
* Class providing test cases for the Bootstrap 5 horizontal Twig form theme.
|
||||
*
|
||||
* @author Romain Monteil <monteil.romain@gmail.com>
|
||||
*/
|
||||
class FormExtensionBootstrap5HorizontalLayoutTest extends AbstractBootstrap5HorizontalLayoutTest
|
||||
{
|
||||
use RuntimeLoaderProvider;
|
||||
|
||||
protected $testableFeatures = [
|
||||
'choice_attr',
|
||||
];
|
||||
|
||||
private $renderer;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$loader = new FilesystemLoader([
|
||||
__DIR__.'/../../Resources/views/Form',
|
||||
__DIR__.'/Fixtures/templates/form',
|
||||
]);
|
||||
|
||||
$environment = new Environment($loader, ['strict_variables' => true]);
|
||||
$environment->addExtension(new TranslationExtension(new StubTranslator()));
|
||||
$environment->addExtension(new FormExtension());
|
||||
|
||||
$rendererEngine = new TwigRendererEngine([
|
||||
'bootstrap_5_horizontal_layout.html.twig',
|
||||
'custom_widgets.html.twig',
|
||||
], $environment);
|
||||
$this->renderer = new FormRenderer($rendererEngine, $this->getMockBuilder(CsrfTokenManagerInterface::class)->getMock());
|
||||
$this->registerTwigRuntimeLoader($environment, $this->renderer);
|
||||
}
|
||||
|
||||
protected function renderForm(FormView $view, array $vars = []): string
|
||||
{
|
||||
return (string) $this->renderer->renderBlock($view, 'form', $vars);
|
||||
}
|
||||
|
||||
protected function renderLabel(FormView $view, $label = null, array $vars = []): string
|
||||
{
|
||||
if (null !== $label) {
|
||||
$vars += ['label' => $label];
|
||||
}
|
||||
|
||||
return (string) $this->renderer->searchAndRenderBlock($view, 'label', $vars);
|
||||
}
|
||||
|
||||
protected function renderHelp(FormView $view): string
|
||||
{
|
||||
return (string) $this->renderer->searchAndRenderBlock($view, 'help');
|
||||
}
|
||||
|
||||
protected function renderErrors(FormView $view): string
|
||||
{
|
||||
return (string) $this->renderer->searchAndRenderBlock($view, 'errors');
|
||||
}
|
||||
|
||||
protected function renderWidget(FormView $view, array $vars = []): string
|
||||
{
|
||||
return (string) $this->renderer->searchAndRenderBlock($view, 'widget', $vars);
|
||||
}
|
||||
|
||||
protected function renderRow(FormView $view, array $vars = []): string
|
||||
{
|
||||
return (string) $this->renderer->searchAndRenderBlock($view, 'row', $vars);
|
||||
}
|
||||
|
||||
protected function renderRest(FormView $view, array $vars = []): string
|
||||
{
|
||||
return (string) $this->renderer->searchAndRenderBlock($view, 'rest', $vars);
|
||||
}
|
||||
|
||||
protected function renderStart(FormView $view, array $vars = []): string
|
||||
{
|
||||
return (string) $this->renderer->renderBlock($view, 'form_start', $vars);
|
||||
}
|
||||
|
||||
protected function renderEnd(FormView $view, array $vars = []): string
|
||||
{
|
||||
return (string) $this->renderer->renderBlock($view, 'form_end', $vars);
|
||||
}
|
||||
|
||||
protected function setTheme(FormView $view, array $themes, $useDefaultThemes = true): void
|
||||
{
|
||||
$this->renderer->setTheme($view, $themes, $useDefaultThemes);
|
||||
}
|
||||
}
|
@ -0,0 +1,165 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Bridge\Twig\Tests\Extension;
|
||||
|
||||
use Symfony\Bridge\Twig\Extension\FormExtension;
|
||||
use Symfony\Bridge\Twig\Extension\TranslationExtension;
|
||||
use Symfony\Bridge\Twig\Form\TwigRendererEngine;
|
||||
use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubTranslator;
|
||||
use Symfony\Component\Form\Extension\Core\Type\FormType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\MoneyType;
|
||||
use Symfony\Component\Form\FormRenderer;
|
||||
use Symfony\Component\Form\FormView;
|
||||
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
|
||||
use Twig\Environment;
|
||||
use Twig\Loader\FilesystemLoader;
|
||||
|
||||
/**
|
||||
* Class providing test cases for the Bootstrap 5 Twig form theme.
|
||||
*
|
||||
* @author Romain Monteil <monteil.romain@gmail.com>
|
||||
*/
|
||||
class FormExtensionBootstrap5LayoutTest extends AbstractBootstrap5LayoutTest
|
||||
{
|
||||
use RuntimeLoaderProvider;
|
||||
|
||||
/**
|
||||
* @var FormRenderer
|
||||
*/
|
||||
private $renderer;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$loader = new FilesystemLoader([
|
||||
__DIR__.'/../../Resources/views/Form',
|
||||
__DIR__.'/Fixtures/templates/form',
|
||||
]);
|
||||
|
||||
$environment = new Environment($loader, ['strict_variables' => true]);
|
||||
$environment->addExtension(new TranslationExtension(new StubTranslator()));
|
||||
$environment->addExtension(new FormExtension());
|
||||
|
||||
$rendererEngine = new TwigRendererEngine([
|
||||
'bootstrap_5_layout.html.twig',
|
||||
'custom_widgets.html.twig',
|
||||
], $environment);
|
||||
$this->renderer = new FormRenderer($rendererEngine, $this->getMockBuilder(CsrfTokenManagerInterface::class)->getMock());
|
||||
$this->registerTwigRuntimeLoader($environment, $this->renderer);
|
||||
}
|
||||
|
||||
public function testStartTagHasNoActionAttributeWhenActionIsEmpty()
|
||||
{
|
||||
$form = $this->factory->create(FormType::class, null, [
|
||||
'method' => 'get',
|
||||
'action' => '',
|
||||
]);
|
||||
|
||||
$html = $this->renderStart($form->createView());
|
||||
|
||||
self::assertSame('<form name="form" method="get">', $html);
|
||||
}
|
||||
|
||||
public function testStartTagHasActionAttributeWhenActionIsZero()
|
||||
{
|
||||
$form = $this->factory->create(FormType::class, null, [
|
||||
'method' => 'get',
|
||||
'action' => '0',
|
||||
]);
|
||||
|
||||
$html = $this->renderStart($form->createView());
|
||||
|
||||
self::assertSame('<form name="form" method="get" action="0">', $html);
|
||||
}
|
||||
|
||||
public function testMoneyWidgetInIso()
|
||||
{
|
||||
$environment = new Environment(new FilesystemLoader([
|
||||
__DIR__.'/../../Resources/views/Form',
|
||||
__DIR__.'/Fixtures/templates/form',
|
||||
]), ['strict_variables' => true]);
|
||||
$environment->addExtension(new TranslationExtension(new StubTranslator()));
|
||||
$environment->addExtension(new FormExtension());
|
||||
$environment->setCharset('ISO-8859-1');
|
||||
|
||||
$rendererEngine = new TwigRendererEngine([
|
||||
'bootstrap_5_layout.html.twig',
|
||||
'custom_widgets.html.twig',
|
||||
], $environment);
|
||||
$this->renderer = new FormRenderer($rendererEngine, $this->getMockBuilder(CsrfTokenManagerInterface::class)->getMock());
|
||||
$this->registerTwigRuntimeLoader($environment, $this->renderer);
|
||||
|
||||
$view = $this->factory
|
||||
->createNamed('name', MoneyType::class)
|
||||
->createView();
|
||||
|
||||
self::assertSame(<<<'HTML'
|
||||
<div class="input-group"><span class="input-group-text">€ </span><input type="text" id="name" name="name" required="required" class="form-control" /></div>
|
||||
HTML
|
||||
, trim($this->renderWidget($view)));
|
||||
}
|
||||
|
||||
protected function renderForm(FormView $view, array $vars = []): string
|
||||
{
|
||||
return (string) $this->renderer->renderBlock($view, 'form', $vars);
|
||||
}
|
||||
|
||||
protected function renderLabel(FormView $view, $label = null, array $vars = []): string
|
||||
{
|
||||
if (null !== $label) {
|
||||
$vars += ['label' => $label];
|
||||
}
|
||||
|
||||
return (string) $this->renderer->searchAndRenderBlock($view, 'label', $vars);
|
||||
}
|
||||
|
||||
protected function renderHelp(FormView $view): string
|
||||
{
|
||||
return (string) $this->renderer->searchAndRenderBlock($view, 'help');
|
||||
}
|
||||
|
||||
protected function renderErrors(FormView $view): string
|
||||
{
|
||||
return (string) $this->renderer->searchAndRenderBlock($view, 'errors');
|
||||
}
|
||||
|
||||
protected function renderWidget(FormView $view, array $vars = []): string
|
||||
{
|
||||
return (string) $this->renderer->searchAndRenderBlock($view, 'widget', $vars);
|
||||
}
|
||||
|
||||
protected function renderRow(FormView $view, array $vars = []): string
|
||||
{
|
||||
return (string) $this->renderer->searchAndRenderBlock($view, 'row', $vars);
|
||||
}
|
||||
|
||||
protected function renderRest(FormView $view, array $vars = []): string
|
||||
{
|
||||
return (string) $this->renderer->searchAndRenderBlock($view, 'rest', $vars);
|
||||
}
|
||||
|
||||
protected function renderStart(FormView $view, array $vars = []): string
|
||||
{
|
||||
return (string) $this->renderer->renderBlock($view, 'form_start', $vars);
|
||||
}
|
||||
|
||||
protected function renderEnd(FormView $view, array $vars = []): string
|
||||
{
|
||||
return (string) $this->renderer->renderBlock($view, 'form_end', $vars);
|
||||
}
|
||||
|
||||
protected function setTheme(FormView $view, array $themes, $useDefaultThemes = true): void
|
||||
{
|
||||
$this->renderer->setTheme($view, $themes, $useDefaultThemes);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user