Skip to content

Form reference

Auto Complete Entity

Imagine you want to write your own repository method, because the search results depend not only on a search term but also on other attributes (e.g. the User, who bought a specific Product). Let's call this method findByTermAndUser. This is, how this method could look like:

php
<?php
namespace App\Repository;

use Enhavo\Bundle\AppBundle\Repository\EntityRepository;

class ProductRepository extends EntityRepository
{

    public function findByTermAndUser($term, $userId, $limit)
    {
        $query = $this->createQueryBuilder('p')
            ->where('p.user = :userId')
            ->andWhere('p.title = :term')
            ->setParameter('userId', sprintf('%s%%', $userId))
            ->setParameter('title', sprintf('%s%%', $term))
        ;

        $result = $query->getQuery()->getArrayResult();

        $paginator = $this->getPaginator($query);
        $paginator->setMaxPerPage($limit);

        return $paginator;
    }
}

That's how a standard Auto-Complete-Entity-Route looks like:

yaml
app_product_auto_complete:
    options:
        expose: true
    path: /app/product/auto_complete
    methods: [GET]
    defaults:
        _controller: enhavo_form.controller.auto_complete:searchAction
        _config:
            class: App\Entity\Product
            repository:
                method: findByTerm

Maybe you have already noticed the problem. That route only works for the standard findByTerm with the two parameters $term and $limit. So how can we add the $userId?

The easiest way is to add a flexible value with the userId, we need to add a value to our path and pick that value to use it as function argument. To use this value from our route as argument for our findByTermAndUser, the Route must have the arguments as follows:

yaml
app_product_auto_complete:
    options:
        expose: true
    path: /app/product/{userId}/auto_complete
    methods: [GET]
    defaults:
        _controller: enhavo_form.controller.auto_complete:searchAction
        _config:
            class: App\Entity\Product
            repository:
                method: findByTermAndUser
                arguments:
                    - expr:configuration.getSearchTerm()
                    - expr:request.get('userId')
                    - expr:configuration.getLimit()

We add all necessary parameters as arguments for our method and use the expr:request.get('param') to get our last missing value. The two other values are already in our expr.configuration and have their own Getter-Methods.

Finally, the last question is, how we add the $userId to our path. To solve this problem, lets add the $userId as route_parameter to our Auto-Complete-Entity-Type like that:

php
<?php

namespace App\Form\Type;

use App\Entity\Product;

class ProductType extends AbstractType
{
    use ContainerAwareTrait;

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
                /** @var User $user */
                $userId = $event->getData()->getId();
                $form = $event->getForm();
                if (!empty($userId) {
                    $form->add('product', AutoCompleteEntityType::class, [
                        'class' => Product::class,
                        'route' => 'app_product_auto_complete',
                        'route_parameters' => [
                            'userId' => $userId
                        ]
                    ]);
                }
        });
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => Product::class
        ]);
    }

    public function getBlockPrefix()
    {
        return 'app_applications_user';
    }
}

Note

Notice, that a Route-Parameter can not be NULL and that we have multiple options, to get our $userId. The easiest way is to use the EventListener like in our example. For more information go to the Symfony Form Events-Documentation . If you want to see the other options, read our and the Symfony Documentation about Forms in general.

Boolean

The form type BooleanType can be used for boolean fields. It renders a true/false radio select.

Field Options

  • default: (true/false/null) The initial value to be set if the value in the resource is null. If this is null (default), none of the checkboxes will be checked.

Currency

The type '' enhavo currency'' can be used for any field, where a currency is needed.

Features

The enhavo currency type converts the database integer value into a full price and vice versa. It works like a natural price field and not like a database field, it is not needed to type 1200, to express 12,00 EUR, which makes it very comfortable for the user.

FormType

php
<?php

use Enhavo\Bundle\FormBundle\Form\Type\CurrencyType;

class YourShopClass extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('price', CurrencyType::class, array(
            'label' => 'Price'
        ));
    }
}

Date

Date Time

Entity Tree

Head Line

List

The enhavo_list helps you to list individual fields on your page. To use the enhavo_list just follow these steps:

  1. Add to FormType
  2. Add to your orm.yml
  3. Add properties

Add to FormType

Add the enhavo_list to your FormType. For the parameter type you can either add a FormType from an Entity you have created or use a doctrine type. You can only add more list items if the allow_add parameter is true. If you want to delete added items, set the allow_delete parameter to true.

In this example we use a doctrine formType.

php
$builder->add('tag', 'enhavo_list', array(
    'type' =>  'text',
    'label' => 'label.tag',
    'prototype' => true,
    'allow_add' => true,
    'by_reference' => false,
    'allow_delete' => true
));

If you want to use your own entity, just replace the type like this:

php
'type' =>  'project_tag',

In this example we added a tag to the enhavo_list.

Add to your orm.yml

Add the list type to your arme.orm.yml . If you added a doctrine type, just add a field with type array like this:

yaml
tag:
    type: array
    nullable: true

If you added your own formType, create a oneToMany relationship. In this case you also have to add some extra code to the add function in your entity:

php
$tag->setAcme($this);

and to the remove function:

php
$this->tags->removeElement($tag);

Add properties

There are two more properties you can add to the formType. Add these like you have done it with the allow_delete property. If you want to separate the items from eachother with a border, set the border property to true. If not you can just skip this step.

php
'border' => false,

If you want to sort the added items, set the sortable property to true.

php
'sortable' => true,

If you have used your own entity, you have to do a few steps more. First you add sortable_property like you have done it with the border and sortable property before.

php
'sortable_property' => 'order'

Then you add a order field to the orm.yml of the entity you have used in the enhavo_list.

yaml
order:
    column: '`order`'
    type: string
    length: 255

After that use the order as a hidden field in the tagType like this:

php
$builder->add('order', 'hidden', array(
          'attr' => array('class' => 'order')
      ));

The name of the class has to be the same you used for the sortable_property.

Message

Poly Collection

This type is used for collections, which need different form types for each item. It will ask the user to select a type if he add a new item.

Basic Usage

php
use Enhavo\Bundle\FormBundle\Form\Type\PolyCollectionType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
// ...

$builder->add('items', PolyCollectionType::class, [
    // a list of entry types, which the user can choose when pressing add button
    'entry_types' => [
        'text' => TextType::class,
        'date' => DateType::class,
    ],
    // these options are passed to type
    'entry_types_options' => [
        'text' => ['label' => 'I am a label'],
        'date' => ['label' => 'Type in the date'],
    ],
    // tell how we know what type the data is
    'entry_type_resolver' => function($data) {
        return $data instanceof DateType ? 'date' : 'text';
    },
]);

Field Options

entry_types

entry_types_options

entry_type_resolver

Position

Slug

Unit

Wysiwyg

This section explains how you can configure your wysiwyg editor system-wide and in some special cases. Enhavo uses the TinyMCE editor, so if you are familiar with its settings you should easily be able to configure it. Otherwise you should also read the TinyMCE configuration docs.

Configuration

You can find the system wide configurations under app/config/wysiwyg.yml. All settings here are equivalent to the TinyMCE configuration, mentioned above. Note that this is a yaml file while the TinyMCE configuration is a Javascript Object or JSON, but yaml can easily be converted to JSON.

These configurations are available:

yaml
height: 150

toolbar1: "undo redo | bold italic underline strikethrough subscript superscript removeformat | link styleselect"

toolbar2: "table | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | code"

style_formats:
    - {title: 'Bold text', inline: 'b'}
    - {title: 'Red text', inline: 'span', styles: {color: '#ff0000'}}
    - {title: 'Red header', block: 'h1', styles: {color: '#ff0000'}}
    - {title: 'Example 1', inline: 'span', classes: 'example1'}
    - {title: 'Example 2', inline: 'span', classes: 'example2'}
    - {title: 'Table styles'}
    - {title: 'Table row 1', selector: 'tr', classes: 'tablerow1'}

formats:
      alignleft: {selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes: 'left'}
      aligncenter: {selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes: 'center'}
      alignright: {selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes: 'right'}
      alignfull: {selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', classes: 'full'}
      bold: {inline: 'span', 'classes': 'bold'}
      italic: {inline: 'span', 'classes': 'italic'}
      underline: {inline: 'span', 'classes': 'underline', exact: true}
      strikethrough: {inline: 'del'}
      customformat: {inline: 'span', styles: {color: '#00ff00', fontSize: '20px'}, attributes: {title: 'My custom format'}}

content_css: ~ # see below

content_css

Since we're using the assets/assetics commands for css file locations, you need to use the "@" syntax for the configuration of content_css.

yaml
#single file
content_css: '@FooBundle/Resources/public/css/styleOne.css'
yaml
#multiple files
content_css:
  - '@FooBundle/Resources/public/css/styleOne.css'
  - '@FooBundle/Resources/public/css/styleTwo.css'

FormType

If you need a special configuration for just one form, you can override or filter some settings in your FormType class, in the option array.

  • formats: Needs an array, where you can list the formats that should be shown.
  • height: Override the height
  • toolbar1: Override the toolbar1
  • toolbar2: Override the toolbar2
  • content_css: Override the content_css, this could be an array or a string (use "@" syntax)
php
$builder->add('text', 'wysiwyg', array(
    'formats' => array('Bold text', 'Red text'),
    'height' => 300,
    'toolbar1' => '',
    'toolbar2' => ''
    'content_css' => array(
        '@FooBundle/Resources/public/css/styleOne.css'
    )
);