form_admin_fields.html.twig 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. {#
  2. This file is part of the Sonata package.
  3. (c) Thomas Rabaix <thomas.rabaix@sonata-project.org>
  4. For the full copyright and license information, please view the LICENSE
  5. file that was distributed with this source code.
  6. #}
  7. {% extends 'form_div_layout.html.twig' %}
  8. {% block form_errors -%}
  9. {% if errors|length > 0 %}
  10. {% if not form.parent %}<div class="alert alert-danger">{% endif %}
  11. <ul class="list-unstyled">
  12. {% for error in errors %}
  13. <li><i class="glyphicon glyphicon-exclamation-sign"></i> {{ error.message }}</li>
  14. {% endfor %}
  15. </ul>
  16. {% if not form.parent %}</div>{% endif %}
  17. {% endif %}
  18. {%- endblock form_errors %}
  19. {% block form_widget -%}
  20. {{ parent() }}
  21. {% if sonata_help is defined and sonata_help %}
  22. <span class="help-block sonata-ba-field-widget-help">{{ sonata_help|raw }}</span>
  23. {% endif %}
  24. {%- endblock form_widget %}
  25. {% block form_widget_simple %}
  26. {% set type = type|default('text') %}
  27. {% if type != 'file' %}
  28. {% set attr = attr|merge({'class': attr.class|default('') ~ ' form-control'}) %}
  29. {% endif %}
  30. {{ parent() }}
  31. {% endblock form_widget_simple %}
  32. {% block textarea_widget %}
  33. {% set attr = attr|merge({'class': attr.class|default('') ~ ' form-control'}) %}
  34. {{ parent() }}
  35. {% endblock textarea_widget %}
  36. {% block money_widget -%}
  37. {% if money_pattern == '{{ widget }}' %}
  38. {{- block('form_widget_simple') -}}
  39. {% else %}
  40. {% set currencySymbol = money_pattern|replace({'{{ widget }}': ''})|trim %}
  41. {% if money_pattern matches '/^{{ widget }}/' %}
  42. <div class="input-group">
  43. {{- block('form_widget_simple') -}}
  44. <span class="input-group-addon">{{ currencySymbol }}</span>
  45. </div>
  46. {% elseif money_pattern matches '/{{ widget }}$/' %}
  47. <div class="input-group">
  48. <span class="input-group-addon">{{ currencySymbol }}</span>
  49. {{- block('form_widget_simple') -}}
  50. </div>
  51. {% endif %}
  52. {% endif %}
  53. {%- endblock money_widget %}
  54. {% block percent_widget %}
  55. {% spaceless %}
  56. {% set type = type|default('text') %}
  57. <div class="input-group">
  58. {{ block('form_widget_simple') }}
  59. <span class="input-group-addon">%</span>
  60. </div>
  61. {% endspaceless %}
  62. {% endblock percent_widget %}
  63. {# Labels #}
  64. {% block form_label %}
  65. {% spaceless %}
  66. {% if label is not sameas(false) and sonata_admin.options['form_type'] == 'horizontal' %}
  67. {% set label_class = 'col-sm-3' %}
  68. {% endif %}
  69. {% set label_class = label_class|default('') ~ ' control-label' %}
  70. {#{{ sonata_admin.admin.getConfigurationPool().getOption('form_type') }}#}
  71. {% if label is not sameas(false) %}
  72. {% set label_attr = label_attr|merge({'class': label_attr.class|default('') ~ label_class }) %}
  73. {% if not compound %}
  74. {% set label_attr = label_attr|merge({'for': id}) %}
  75. {% endif %}
  76. {% if required %}
  77. {% set label_attr = label_attr|merge({'class': (label_attr.class|default('') ~ ' required')|trim}) %}
  78. {% endif %}
  79. {% if label is empty %}
  80. {% set label = name|humanize %}
  81. {% endif %}
  82. {% if in_list_checkbox is defined and in_list_checkbox and widget is defined %}
  83. <label{% for attrname,attrvalue in attr %} {{attrname}}="{{attrvalue}}"{% endfor %}>
  84. {{ widget|raw }}
  85. <span>
  86. {% if not sonata_admin.admin %}
  87. {{- label|trans({}, translation_domain) -}}
  88. {% else %}
  89. {{- label|trans({}, sonata_admin.field_description.translationDomain) -}}
  90. {% endif%}
  91. </span>
  92. </label>
  93. {% else %}
  94. <label{% for attrname, attrvalue in label_attr %} {{ attrname }}="{{ attrvalue }}"{% endfor %}>
  95. {% if not sonata_admin.admin%}
  96. {{- label|trans({}, translation_domain) -}}
  97. {% else %}
  98. {{ sonata_admin.admin.trans(label, {}, sonata_admin.field_description.translationDomain) }}
  99. {% endif %}
  100. </label>
  101. {% endif %}
  102. {% endif %}
  103. {% endspaceless %}
  104. {% endblock form_label %}
  105. {% block choice_widget_expanded %}
  106. {% spaceless %}
  107. {% set attr = attr|merge({'class': attr.class|default('') ~ ' list-unstyled'}) %}
  108. <ul {{ block('widget_container_attributes') }}>
  109. {% for child in form %}
  110. <li>
  111. {% set form_widget_content %}
  112. {{ form_widget(child, {'horizontal': false, 'horizontal_input_wrapper_class': ''}) }} {# {'horizontal': false, 'horizontal_input_wrapper_class': ''} needed to avoid MopaBootstrapBundle messing with the DOM #}
  113. {% endset %}
  114. {{ form_label(child, child.vars.label|default(null), { 'in_list_checkbox' : true, 'widget' : form_widget_content } ) }}
  115. </li>
  116. {% endfor %}
  117. </ul>
  118. {% endspaceless %}
  119. {% endblock choice_widget_expanded %}
  120. {% block choice_widget_collapsed %}
  121. {% spaceless %}
  122. {% if required and empty_value is none and not empty_value_in_choices and not multiple %}
  123. {% set required = false %}
  124. {% endif %}
  125. {% set attr = attr|merge({'class': attr.class|default('') ~ ' form-control'}) %}
  126. {% if sortable and multiple %}
  127. {{ block('sonata_type_choice_multiple_sortable') }}
  128. {% else %}
  129. <select {{ block('widget_attributes') }}{% if multiple %} multiple="multiple"{% endif %} >
  130. {% if empty_value is not none %}
  131. <option value=""{% if required and value is empty %} selected="selected"{% endif %}>
  132. {% if not sonata_admin.admin %}
  133. {{- empty_value|trans({}, translation_domain) -}}
  134. {% else %}
  135. {{- empty_value|trans({}, sonata_admin.field_description.translationDomain) -}}
  136. {% endif%}
  137. </option>
  138. {% endif %}
  139. {% if preferred_choices|length > 0 %}
  140. {% set options = preferred_choices %}
  141. {{ block('choice_widget_options') }}
  142. {% if choices|length > 0 %}
  143. <option disabled="disabled">{{ separator }}</option>
  144. {% endif %}
  145. {% endif %}
  146. {% set options = choices %}
  147. {{ block('choice_widget_options') }}
  148. </select>
  149. {% endif %}
  150. {% endspaceless %}
  151. {% endblock choice_widget_collapsed %}
  152. {% block date_widget %}
  153. {% spaceless %}
  154. {% if widget == 'single_text' %}
  155. {{ block('form_widget_simple') }}
  156. {% else %}
  157. {% if row is not defined or row == true %}
  158. {% set attr = attr|merge({'class': attr.class|default('') ~ ' row' }) %}
  159. {% endif %}
  160. {% set input_wrapper_class = input_wrapper_class|default('col-sm-4') %}
  161. <div {{ block('widget_container_attributes') }}>
  162. {{ date_pattern|replace({
  163. '{{ year }}': '<div class="'~ input_wrapper_class ~ '">' ~ form_widget(form.year) ~ '</div>',
  164. '{{ month }}': '<div class="'~ input_wrapper_class ~ '">' ~ form_widget(form.month) ~ '</div>',
  165. '{{ day }}': '<div class="'~ input_wrapper_class ~ '">' ~ form_widget(form.day) ~ '</div>',
  166. })|raw }}
  167. </div>
  168. {% endif %}
  169. {% endspaceless %}
  170. {% endblock date_widget %}
  171. {% block time_widget %}
  172. {% spaceless %}
  173. {% if widget == 'single_text' %}
  174. {{ block('form_widget_simple') }}
  175. {% else %}
  176. {% if row is not defined or row == true %}
  177. {% set attr = attr|merge({'class': attr.class|default('') ~ ' row' }) %}
  178. {% endif %}
  179. {% set input_wrapper_class = input_wrapper_class|default('col-sm-6') %}
  180. <div {{ block('widget_container_attributes') }}>
  181. <div class="{{ input_wrapper_class }}">
  182. {{ form_widget(form.hour) }}
  183. </div>
  184. {% if with_minutes %}
  185. <div class="{{ input_wrapper_class }}">
  186. {{ form_widget(form.minute) }}
  187. </div>
  188. {% endif %}
  189. {% if with_seconds %}
  190. <div class="{{ input_wrapper_class }}">
  191. {{ form_widget(form.second) }}
  192. </div>
  193. {% endif %}
  194. </div>
  195. {% endif %}
  196. {% endspaceless %}
  197. {% endblock time_widget %}
  198. {% block datetime_widget %}
  199. {% spaceless %}
  200. {% if widget == 'single_text' %}
  201. {{ block('form_widget_simple') }}
  202. {% else %}
  203. {% set attr = attr|merge({'class': attr.class|default('') ~ ' row' }) %}
  204. <div {{ block('widget_container_attributes') }}>
  205. {{ form_errors(form.date) }}
  206. {{ form_errors(form.time) }}
  207. {{ form_widget(form.date, {'row': false, 'input_wrapper_class': 'col-sm-2'}) }}
  208. {{ form_widget(form.time, {'row': false, 'input_wrapper_class': 'col-sm-2'}) }}
  209. </div>
  210. {% endif %}
  211. {% endspaceless %}
  212. {% endblock datetime_widget %}
  213. {% block form_row %}
  214. <div class="form-group{% if errors|length > 0 %} has-error{% endif %}" id="sonata-ba-field-container-{{ id }}">
  215. {% set label = sonata_admin.field_description.options.name|default(label) %}
  216. {% set div_class = 'sonata-ba-field' %}
  217. {% if label is sameas(false) %}
  218. {% set div_class = div_class ~ ' sonata-collection-row-without-label' %}
  219. {% endif %}
  220. {% if sonata_admin.options['form_type'] == 'horizontal' %}
  221. {% if label is sameas(false) %}
  222. {% if 'collection' in form.parent.vars.block_prefixes %}
  223. {% set div_class = div_class ~ ' col-sm-12' %}
  224. {% else %}
  225. {% set div_class = div_class ~ ' col-sm-9 col-sm-offset-3' %}
  226. {% endif %}
  227. {% else %}
  228. {% set div_class = div_class ~ ' col-sm-9' %}
  229. {% endif %}
  230. {% endif %}
  231. {{ form_label(form, label|default(null)) }}
  232. {% if sonata_admin is defined and sonata_admin_enabled %}
  233. {% set div_class = div_class ~ ' sonata-ba-field-' ~ sonata_admin.edit ~ '-' ~ sonata_admin.inline %}
  234. {% if sonata_admin.edit == 'inline' and sonata_admin.inline == 'table' %}
  235. {% set div_class = div_class ~ ' form-inline' %}
  236. {% endif %}
  237. {% endif %}
  238. {% if errors|length > 0 %}
  239. {% set div_class = div_class ~ ' sonata-ba-field-error' %}
  240. {% endif %}
  241. <div class="{{ div_class }}">
  242. {{ form_widget(form, {'horizontal': false, 'horizontal_input_wrapper_class': ''}) }} {# {'horizontal': false, 'horizontal_input_wrapper_class': ''} needed to avoid MopaBootstrapBundle messing with the DOM #}
  243. {% if errors|length > 0 %}
  244. <div class="help-block sonata-ba-field-error-messages">
  245. {{ form_errors(form) }}
  246. </div>
  247. {% endif %}
  248. {% if sonata_admin is defined and sonata_admin_enabled and sonata_admin.field_description.help|default(false) %}
  249. <span class="help-block sonata-ba-field-help">{{ sonata_admin.admin.trans(sonata_admin.field_description.help, {}, sonata_admin.field_description.translationDomain)|raw }}</span>
  250. {% endif %}
  251. </div>
  252. </div>
  253. {% endblock form_row %}
  254. {% block sonata_type_native_collection_widget_row %}
  255. {% spaceless %}
  256. <div class="sonata-collection-row">
  257. {% if allow_delete %}
  258. <div class="row">
  259. <div class="col-xs-1">
  260. <a href="#" class="btn btn-link sonata-collection-delete">
  261. <i class="fa fa-minus-circle"></i>
  262. </a>
  263. </div>
  264. <div class="col-xs-11">
  265. {% endif %}
  266. {{ form_row(child, { label: false }) }}
  267. {% if allow_delete %}
  268. </div>
  269. </div>
  270. {% endif %}
  271. </div>
  272. {% endspaceless %}
  273. {% endblock sonata_type_native_collection_widget_row %}
  274. {% block sonata_type_native_collection_widget %}
  275. {% spaceless %}
  276. {% if prototype is defined %}
  277. {% set child = prototype %}
  278. {% set attr = attr|merge({'data-prototype': block('sonata_type_native_collection_widget_row'), 'data-prototype-name': prototype.vars.name, 'class': attr.class|default('') }) %}
  279. {% endif %}
  280. <div {{ block('widget_container_attributes') }}>
  281. {{ form_errors(form) }}
  282. {% for child in form %}
  283. {{ block('sonata_type_native_collection_widget_row') }}
  284. {% endfor %}
  285. {{ form_rest(form) }}
  286. {% if allow_add %}
  287. <div><a href="#" class="btn btn-link sonata-collection-add"><i class="fa fa-plus-circle"></i></a></div>
  288. {% endif %}
  289. </div>
  290. {% endspaceless %}
  291. {% endblock sonata_type_native_collection_widget %}
  292. {% block sonata_type_immutable_array_widget %}
  293. {% spaceless %}
  294. <div {{ block('widget_container_attributes') }}>
  295. {{ form_errors(form) }}
  296. {% for key, child in form %}
  297. {{ block('sonata_type_immutable_array_widget_row') }}
  298. {% endfor %}
  299. {{ form_rest(form) }}
  300. </div>
  301. {% endspaceless %}
  302. {% endblock sonata_type_immutable_array_widget %}
  303. {% block sonata_type_immutable_array_widget_row %}
  304. {% spaceless %}
  305. <div class="form-group{% if child.vars.errors|length > 0%} error{%endif%}" id="sonata-ba-field-container-{{ id }}-{{ key }}">
  306. {{ form_label(child) }}
  307. {% set div_class = "" %}
  308. {% if sonata_admin.options['form_type'] == 'horizontal' %}
  309. {% set div_class = 'col-sm-9' %}
  310. {% endif%}
  311. <div class="{{ div_class }} sonata-ba-field sonata-ba-field-{{ sonata_admin.edit }}-{{ sonata_admin.inline }} {% if child.vars.errors|length > 0 %}sonata-ba-field-error{% endif %}">
  312. {{ form_widget(child, {'horizontal': false, 'horizontal_input_wrapper_class': ''}) }} {# {'horizontal': false, 'horizontal_input_wrapper_class': ''} needed to avoid MopaBootstrapBundle messing with the DOM #}
  313. </div>
  314. {% if child.vars.errors|length > 0 %}
  315. <div class="help-block sonata-ba-field-error-messages">
  316. {{ form_errors(child) }}
  317. </div>
  318. {% endif %}
  319. </div>
  320. {% endspaceless %}
  321. {% endblock %}
  322. {% block sonata_type_model_autocomplete_widget %}
  323. {% include template %}
  324. {% endblock sonata_type_model_autocomplete_widget %}
  325. {% block sonata_type_choice_field_mask_widget %}
  326. {{ block('choice_widget') }}
  327. {% set main_form_name = id|slice(0, id|length - name|length) %}
  328. <script>
  329. jQuery(document).ready(function() {
  330. var allFields = {{ all_fields|json_encode|raw }};
  331. var map = {{ map|json_encode|raw }};
  332. showMaskChoiceEl = jQuery('#{{ main_form_name }}{{ name }}');
  333. showMaskChoiceEl.on('change', function () {
  334. choice_field_mask_show(jQuery(this).val());
  335. });
  336. function choice_field_mask_show(val)
  337. {
  338. var controlGroupIdFunc = function (field) {
  339. return '#sonata-ba-field-container-{{ main_form_name }}' + field;
  340. };
  341. if (map[val] == undefined) {
  342. jQuery.each(allFields, function (i, field) {
  343. jQuery(controlGroupIdFunc(field)).hide();
  344. });
  345. return;
  346. }
  347. jQuery.each(allFields, function (i, field) {
  348. jQuery(controlGroupIdFunc(field)).hide();
  349. });
  350. jQuery.each(map[val], function (i, field) {
  351. jQuery(controlGroupIdFunc(field)).show();
  352. });
  353. }
  354. choice_field_mask_show(showMaskChoiceEl.val());
  355. });
  356. </script>
  357. {% endblock %}
  358. {% block sonata_type_choice_multiple_sortable %}
  359. <input type="hidden" name="{{ full_name }}" id="{{ id }}" value="{{ value|join(',') }}" />
  360. <script>
  361. jQuery(document).ready(function() {
  362. var $target = jQuery('#{{ id }}');
  363. Admin.setup_sortable_select2($target, {{ form.vars.choices|json_encode|raw }});
  364. });
  365. </script>
  366. {% endblock %}