# What is an Uitype?

## Definition

An uitype is a graphical element used to represent a form field and format its value according to a context.

Uccello allows you to create forms made up of fields of different types. Each **field type** corresponds to a uitype.

Each uitype is **autonomous**, **independent** and **able to format** data:

* In a  database
* In a vue
* In table cells
* In the response to an API call

Similarly, each uitype is able to generate a form field to display on an edit page.

## Flexible

Thanks to the high flexibility of uccello, it is possible to create **simplistic** uitypes (a simple value) as well as **complex** uitypes (display using external libraries).

For example, the `text` uitype only displays plain text while the `entity` uitype is able to link one data to another that may be located in a different module. The `date` uitype allows you to select a date from a calendar.

## Configurable

The configuration of a uitype is done at several levels.

* `migration` file: Type of the column in the database and type of field used in the form
* `php` class: Formatting the value when saving and displaying
* `blade` files : Displaying the form field and defining a layout in a view

Let's take the example of the `text`  uitype:

### **Migration file**

```php
// Creation of the table
Schema::create('people', function (Blueprint $table) {
    $table->increments('id');
    $table->string('name'); // This column will be link to a text uitype
    $table->timestamps();
});

...

// Creation of the field
$field = Field::create([
    'name' => 'name',
    'uitype_id' => uitype('text')->id, // Use of the text uitype
    'displaytype_id' => displaytype('everywhere')->id,
    'sequence' => 0,
    'block_id' => $block->id,
    'module_id' => $module->id
]);
```

`$table->string('name')` : Creta a column named`name` with type `VARCHAR(255)`

`'uitype_id' => uitype('text')->id` : The field uses the `text` uitype

### **Php class**

The `text` uitype is defined in the file `app/Fields/Uitype/Text.php`. Here is a summary after integration of the traits used.

```php
namespace Uccello\Core\Fields\Uitype;

use Uccello\Core\Contracts\Field\Uitype;
use Uccello\Core\Fields\Traits\DefaultUitype;
use Uccello\Core\Fields\Traits\UccelloUitype;
use Uccello\Core\Models\Field;
use Uccello\Core\Models\Module;
use Uccello\Core\Models\Domain;

class Text implements Uitype
{
    /**
     * Name of the package in which the uitype is located
     * Useful for Blade to find the associated template files
     */
    public $package = 'uccello';

    /**
     * Field type used by Form builder
     */
    public function getFormType(): string
    {
        return 'text';
    }

    /**
     * Field options used by Form Builder
     */
    public function getFormOptions($record, Field $field, Module $module): array
    {
        return [];
    }

    /**
     * Default database column name
     */
    public function getDefaultDatabaseColumn(Field $field) : string
    {
        return $field->name;
    }

    /**
     * Default icon to use in the form field
     */
    public function getDefaultIcon() : ?string
    {
        return null;
    }

    /**
     * Formatting the value for a display in a view or in an API response
     */
    public function getFormattedValueToDisplay(Field $field, $record) : string
    {
        return $record->{$field->column} ?? '';
    }

    /**
     * Formatting the value before saving it in the database
     */
    public function getFormattedValueToSave(Request $request, Field $field, $value, $record = null, ?Domain $domain = null, ?Module $module = null) : ?string
    {
        return $value;
    }
    
    /**
     * Returns formatted value to save with config.
     *
     * @param \Illuminate\Http\Request $request
     * @param \Uccello\Core\Models\Field $field
     * @param mixed|null $value
     * @param mixed|null $record
     * @param \Uccello\Core\Models\Domain|null $domain
     * @param \Uccello\Core\Models\Module|null $module
     * @return string|null
     */
    public function getFormattedValueToSaveWithConfig(Request $request, Field $field, $value, $config, $record = null, ?Domain $domain = null, ?Module $module = null) : ?string
    {
        return $this->getFormattedValueToSave($request, $field, $value, $record, $domain, $module);
    }

    /**
     * Formatting the value before searching the database.
     * By default adds % at the beginning end the ending to make a 'like' query.
     */
    public function getFormattedValueToSearch($value)
    {
        $formattedValue = $value;

        if ($formattedValue) {
            $formattedValue = "%$value%";
        }

        return $formattedValue;
    }

    /**
     * Adding the condition in the SQL query
     */
    public function addConditionToSearchQuery(Builder $query, Field $field, $value) : Builder
    {
        if (!$this->isEmptyOrNotEmptySearchQuery($query, $field, $value)) {
            $formattedValue = $this->getFormattedValueToSearch($value);
            $query = $query->where($field->column, 'like', $formattedValue);
        }

        return $query;
    }
    
   /**
    * Returns true if the search value is 'Null' or 'NotNull'
    */
    protected function isEmptyOrNotEmptySearchQuery(Builder &$query, Field $field, $value): bool
    {
        if ($value === uctrans('filter.search_flag.empty', $field->module)) {
            $query->where(function ($q) use ($field) {
                $q->whereNull($field->column)
                    ->orWhere($field->column, '=', '');
            });
            return true;
        } elseif ($value === uctrans('filter.search_flag.not_empty', $field->module)) {
            $query = $query->whereNotNull($field->column)
                            ->where($field->column, '!=', '');
            return true;
        }

        return false;
    }
    
    /**
     * Ask the user some specific options relative to a field.
     * Useful with Module Designer.
     */
    public function askFieldOptions(\StdClass &$module, \StdClass &$field, InputInterface $input, OutputInterface $output)
    {
        $repeated = $output->confirm('Would you like to repeat this field (for confirmation)?', false);

        if ($repeated) {
            $field->data->repeated = true;
        }
    }
    
    /**
     * Way to create the column into the database.
     * Useful for Module Designer.
     */
    public function createFieldColumn(Field $field, Blueprint $table) : Fluent
    {
        return $table->string($this->getDefaultDatabaseColumn($field));
    }
    
    /**
     * Text to add into the module migration.*
     * Useful for Module Designer.
     */
    public function createFieldColumnStr(Field $field) : string
    {
        $column = $this->getDefaultDatabaseColumn($field);
        return "\$table->string('$column')";
    }
}
```

### **Blade files**

There are at least **four blade files** per uitype. One for the layout of the form field in the edit view, one for displaying the field value in the detail view, one for searching from the list view and one for displaying the field value in the list view.

By default, the `text` uitype uses blade files:

* `resources/views/modules/default/uitypes/edit/text.blade.php`
* `resources/views/modules/default/uitypes/detail/text.blade.php`
* `resources/views/modules/default/uitypes/list/text.blade.php`
* `resources/views/modules/default/uitypes/search/text.blade.php`

Here is the content of the file `resources/views/modules/default/uitypes/detail/text.blade.php`.

```markup
<?php $isLarge = $forceLarge ?? $field->data->large ?? false; ?>
<div class="col m2 s5 field-label">
    <?php $label = uctrans($field->label, $module); ?>
    <b title="{{ $label }}">{{ $label }}</b>
</div>
<div class="col {{ $isLarge ? 's7 m10' : 's7 m4' }}">
    <?php
        $value = uitype($field->uitype_id)->getFormattedValueToDisplay($field, $record);
    ?>
    @if ($value)
        <div class="truncate">
            {{ $value }}
        </div>
    @else
        &nbsp;
    @endif
</div>
```

Notice the use of the method `getFormattedValueToDisplay(Field $field, $record)` defined in the`php` class.

## Expandable

Thanks to the fact that each uitype is **autonomous** and **independent**, it is possible to create new ones and share them with the uccello community.

## Default Uitypes

Uccello's default uitypes are found in the directory [vendor/uccello/uccello/app/Fields/Uitype](https://github.com/uccellolabs/uccello/tree/master/app/Fields/Uitype).

To get an overview of all native uitypes, you can go to the [Default Uitypes](https://uccello.gitbook.io/doc/uitypes-displaytypes/default-uitypes) page.
