Skip to content

Commit

Permalink
feature #211 Added the new form_theme design option and simplified fo…
Browse files Browse the repository at this point in the history
…rms (javiereguiluz)

This PR was squashed before being merged into the master branch (closes #211).

Discussion
----------

Added the new form_theme design option and simplified forms

This is the third PR related to #208.

I'm very excited with this PR because this option is very powerful and it has allowed us to do a drastic form code simplification.

Commits
-------

2672587 Added the new form_theme design option and simplified forms
  • Loading branch information
javiereguiluz committed Apr 2, 2015
2 parents 58b2959 + 2672587 commit d69115e
Show file tree
Hide file tree
Showing 120 changed files with 1,226 additions and 267 deletions.
49 changes: 36 additions & 13 deletions Controller/AdminController.php
Expand Up @@ -421,8 +421,40 @@ protected function findBy($entityClass, $searchQuery, array $searchableFields, $
*/
protected function createEditForm($entity, array $entityProperties)
{
return $this->createEntityForm($entity, $entityProperties, 'edit');
}

/**
* Creates the form used to create an entity.
*
* @param object $entity
* @param array $entityProperties
*
* @return Form
*/
protected function createNewForm($entity, array $entityProperties)
{
return $this->createEntityForm($entity, $entityProperties, 'new');
}

/**
* Creates the form used to create or edit an entity.
*
* @param object $entity
* @param array $entityProperties
* @param string $view The name of the view where this form is used ('new' or 'edit')
*
* @return Form
*/
protected function createEntityForm($entity, array $entityProperties, $view)
{
$formCssClass = array_reduce($this->config['design']['form_theme'], function($previousClass, $formTheme) {
return sprintf('theme_%s %s', strtolower(str_replace('.html.twig', '', basename($formTheme))), $previousClass);
});

$form = $this->createFormBuilder($entity, array(
'data_class' => $this->entity['class'],
'attr' => array('class' => $formCssClass, 'id' => $view.'-form'),
));

foreach ($entityProperties as $name => $metadata) {
Expand All @@ -440,25 +472,16 @@ protected function createEditForm($entity, array $entityProperties)
}
}

$formFieldOptions['attr']['field_type'] = $metadata['fieldType'];
$formFieldOptions['attr']['field_css_class'] = $metadata['class'];
$formFieldOptions['attr']['field_help'] = $metadata['help'];

$form->add($name, $metadata['fieldType'], $formFieldOptions);
}

return $form->getForm();
}

/**
* Creates the form used to create an entity.
*
* @param object $entity
* @param array $entityProperties
*
* @return Form
*/
protected function createNewForm($entity, array $entityProperties)
{
return $this->createEditForm($entity, $entityProperties);
}

/**
* It returns the name of the first entity configured in the backend. It's
* mainly used to redirect the homepage of the backend to the listing of the
Expand Down
19 changes: 18 additions & 1 deletion DependencyInjection/Configuration.php
Expand Up @@ -203,11 +203,28 @@ private function addDesignSection(ArrayNodeDefinition $rootNode)
->defaultValue('default')
->info('The theme used to render the backend pages. For now this value can only be "default".')
->validate()
->ifNotInArray(array('default'))
->ifNotInArray(array('default'))
->thenInvalid('The theme name can only be "default".')
->end()
->end()

->variableNode('form_theme')
->defaultValue(array('@EasyAdmin/form/bootstrap_3_horizontal_layout.html.twig'))
->treatNullLike(array('@EasyAdmin/form/bootstrap_3_horizontal_layout.html.twig'))
->info('The form theme applied to backend forms. Allowed values: "horizontal", "vertical" and a custom theme path or array of custom theme paths.')
->validate()
->ifTrue(function ($v) { return 'horizontal' === $v; })
->then(function () { return array('@EasyAdmin/form/bootstrap_3_horizontal_layout.html.twig'); })
->end()
->validate()
->ifTrue(function ($v) { return 'vertical' === $v; })
->then(function () { return array('@EasyAdmin/form/bootstrap_3_layout.html.twig'); })
->end()
->validate()
->ifString()->then(function($v) { return array($v); })
->end()
->end()

->arrayNode('assets')
->performNoDeepMerging()
->addDefaultsIfNotSet()
Expand Down
84 changes: 84 additions & 0 deletions Resources/doc/10-customizing-design.md
Expand Up @@ -26,6 +26,90 @@ easy_admin:
# ...
```

Customizing Form Design
-----------------------

By default, forms are displayed using the **horizontal style** defined by the
Bootstrap 3 CSS framework:

![Default horizontal form style](images/easyadmin-form-horizontal.png)

The style of the forms can be changed application-wide using the `form_theme`
option inside the `design` configuration section. In fact, the default form
style is equivalent to using this configuration:

```yaml
easy_admin:
design:
form_theme: 'horizontal'
# ...
```

If you prefer to display your forms using the **vertical style** defined by
Bootstrap, change the value of this option to `vertical`:

```yaml
easy_admin:
design:
form_theme: 'vertical'
# ...
```

The same form shown previously will now be rendered as follows:

![Vertical form style](images/easyadmin-form-vertical.png)

The `horizontal` and `vertical` values are just nice shortcuts to use any of
the two built-in form themes. But you can also use your own form themes. Just
set the full theme path as the value of the `form_theme` option:

```yaml
easy_admin:
design:
form_theme: '@AppBundle/form/custom_layout.html.twig'
# ...
```

You can even pass several form themes paths in an array to use all of them when
rendering the backend forms:

```yaml
easy_admin:
design:
form_theme:
- '@AppBundle/form/custom_layout.html.twig'
- 'form_div_layout.html.twig'
# ...
```

### Multiple-Column Forms

EasyAdmin doesn't provide any mechanism to create multi-column form layouts.
However, you can use the `class` form field to create these advanced layouts.
The `class` value is applied to the parent `<div>` element which contains the
field label, the field widget, the field help and the optional field errors:

![Multi-column form](images/easyadmin-form-multi-column.png)

The configuration used to display this form is the following:

```yaml
easy_admin:
design:
form_theme: 'vertical'
entities:
Product:
# ...
form:
fields:
- { property: name, class: 'col-sm-12' }
- { property: price, type: 'number', help: 'Prices are always in euros', class: 'col-sm-6' }
- { property: 'ean', label: 'EAN', help: 'EAN 13 valid code. Leave empty if unknown.', class: 'col-sm-6' }
- { property: 'enabled', class: 'col-sm-12' }
- { property: 'description', class: 'col-sm-12' }
# ...
```

Adding Custom Web Assets
------------------------

Expand Down
6 changes: 4 additions & 2 deletions Resources/doc/6-customizing-new-edit-views.md
Expand Up @@ -177,8 +177,10 @@ These are the options that you can define for form fields:
* `help` (optional): the help message that will be displayed below the
form field.
* `class` (optional): the CSS class that will be applied to the form field
widget. For example, to display a big input field, use the Bootstrap 3
class called `input-lg`.
widget container element. For example, when using the default Bootstrap
based form theme, this value is applied to the `<div class="form-group">`
element which wraps the label, the widget and the error messages of the
field.

### Translate Form Field Labels

Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Resources/doc/images/easyadmin-form-vertical.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
28 changes: 28 additions & 0 deletions Resources/public/stylesheet/admin.css
Expand Up @@ -706,6 +706,20 @@ body.new form textarea {
body.new form .form-inline select + select {
margin-left: .5em;
}
body.new form .field_collection_action {
margin-top: -15px;
}

body.new form.theme_bootstrap_3_horizontal_layout #form-actions-row {
padding-left: 15px;
padding-right: 15px;
}

@media (min-width: 768px) {
body.new form.theme_bootstrap_3_horizontal_layout #form-actions-row {
margin-left: 16.66666667%;
}
}

/* -------------------------------------------------------------------------
EDIT PAGE
Expand All @@ -716,6 +730,20 @@ body.edit form textarea {
body.edit form .form-inline select + select {
margin-left: .5em;
}
body.edit form .field_collection_action {
margin-top: -15px;
}

body.edit form.theme_bootstrap_3_horizontal_layout #form-actions-row {
padding-left: 15px;
padding-right: 15px;
}

@media (min-width: 768px) {
body.edit form.theme_bootstrap_3_horizontal_layout #form-actions-row {
margin-left: 16.66666667%;
}
}

/* -------------------------------------------------------------------------
SHOW PAGE
Expand Down
98 changes: 5 additions & 93 deletions Resources/views/edit.html.twig
Expand Up @@ -5,7 +5,7 @@
{% trans_default_domain "EasyAdminBundle" %}
{% set _trans_parameters = { '%entity_name%': _entity.label|trans, '%entity_id%': attribute(item, _entity.primary_key_field_name) } %}

{% form_theme form '@EasyAdmin/form/bootstrap_3_horizontal_layout.html.twig' %}
{% form_theme form with easyadmin_config('design.form_theme') %}

{% block body_class 'admin edit ' ~ _entity.name|lower %}

Expand All @@ -14,98 +14,10 @@
{% endblock %}

{% block main %}
{{ form_start(form, { attr: { id: 'edit-form', novalidate: 'novalidate' } }) }}
<div id="form">
{% for field in form.children if field.vars.name != '_token' %}
{% set _field_metadata = entity_fields[field.vars.name] %}
<div class="form-group {% if not field.vars.valid %}has-error{% endif %}">
{% if _field_metadata['fieldType'] == 'association' %}
{{ easyadmin_render_field_for_edit_view(item, _field_metadata) }}
{% else %}
{% set field_label = _field_metadata['label']|default(null) %}
{{ form_label(field, field_label|trans(_trans_parameters), { label_attr: { class: 'col-sm-2 control-label' } }) }}

<div class="col-sm-10 {% if _field_metadata['fieldType'] == 'checkbox' %}col-sm-offset-2{% endif %}">
{% set widget_attributes = { attr: { class: _field_metadata['class']|default(null) }, label: _field_metadata['label']|trans } %}
{{ form_widget(field, widget_attributes) }}
{{ form_errors(field) }}

{% if _field_metadata['help'] is defined %}
<span class="help-block">{{ _field_metadata['help'] }}</span>
{% endif %}

{% if _field_metadata['fieldType'] == 'collection' %}
{% set add_item_javascript %}
$(function() {
if(event.preventDefault) event.preventDefault(); else event.returnValue = false;

var collection = $('#form_{{ field.vars.name|escape('js') }}');
var numItems = collection.children('div.form-group').length;

var newItem = collection.attr('data-prototype')
.replace(/__name__label__/g, numItems)
.replace(/__name__/g, numItems)
;

collection.append(newItem);
});
{% endset %}
<a href="#" onclick="{{ add_item_javascript|raw }}" class="{{ field|length > 0 ? 'pull-right' : '' }}">
<i class="fa fa-plus-square"></i>
{{ field|length == 0 ? 'Add a new item' : 'Add another item' }}
</a>

{% endif %}
</div>
{% endif %}
</div>
{% endfor %}

<div class="form-group">
<div class="col-sm-10 col-sm-offset-2">
{# the 'save' action is hardcoded for the 'edit' view #}
<button type="submit" class="btn">
<i class="fa fa-save"></i> {{ 'action.save'|trans(_trans_parameters) }}
</button>

{% set _edit_actions = easyadmin_get_actions_for_edit_item(_entity.name) %}
{% for _action in _edit_actions %}
{% if 'method' == _action.type %}
{% set _action_href = path('admin', { action: _action.name, view: 'edit', entity: _entity.name, id: attribute(item, _entity.primary_key_field_name) }) %}
{% elseif 'route' == _action.type %}
{% set _action_href = path(_action.name, { entity: _entity.name, id: attribute(item, _entity.primary_key_field_name) }) %}
{% endif %}

<a class="btn {{ _action.class|default('') }}" href="{{ _action_href }}">
{% if _action.icon %}<i class="fa fa-{{ _action.icon }}"></i>{% endif %}
{{ _action.label|trans(_trans_parameters) }}
</a>
{% endfor %}

{% if easyadmin_action_is_enabled_for_edit_view('delete', _entity.name) %}
{% set _action = easyadmin_get_action_for_edit_view('delete', _entity.name) %}
<button type="button" id="button-delete" class="btn {{ _action.class|default('btn-danger') }}">
{% if _action.icon %}<i class="fa fa-{{ _action.icon }}"></i>{% endif %}
{{ _action.label|default('action.delete')|trans(_trans_parameters) }}
</button>
{% endif %}

{# for aesthetic reasons, the 'list' action is always displayed as a link instead of a button #}
{% if easyadmin_action_is_enabled_for_edit_view('list', _entity.name) %}
{% set _action = easyadmin_get_action_for_edit_view('list', _entity.name) %}
<a class="btn btn-secondary" href="{{ path('admin', ({ entity: _entity.name, action: _action.name, view: 'edit' }) ) }}">{% spaceless %}
{% if _action.icon %}<i class="fa fa-{{ _action.icon }}"></i>{% endif %}
{{ _action.label|default('action.list')|trans(_trans_parameters) }}
{% endspaceless %}</a>
{% endif %}
</div>
</div>
</div>
{{ form_end(form) }}
{{ include('@EasyAdmin/form/entity_form.html.twig', { view: 'edit' }) }}

{{ form(delete_form, { attr: { id: 'delete-form', style: 'display: none' }}) }}


<div id="modal-delete" class="modal fade">
<div class="modal-dialog">
<div class="modal-content">
Expand All @@ -119,10 +31,10 @@
</button>

{% if easyadmin_action_is_enabled_for_edit_view('delete', _entity.name) %}
{% set _action = easyadmin_get_action_for_edit_view('delete', _entity.name) %}
{% set _delete_action = easyadmin_get_action_for_edit_view('delete', _entity.name) %}
<button type="button" data-dismiss="modal" class="btn btn-danger" id="modal-delete-button">
{% if _action.icon %}<i class="fa fa-{{ _action.icon }}"></i>{% endif %}
{{ _action.label|default('action.delete')|trans(_trans_parameters) }}
{% if _delete_action.icon %}<i class="fa fa-{{ _delete_action.icon }}"></i>{% endif %}
{{ _delete_action.label|default('action.delete')|trans(_trans_parameters) }}
</button>
{% endif %}
</div>
Expand Down

0 comments on commit d69115e

Please sign in to comment.