Backpack for Laravel

Backpack for Laravel

A collection of Laravel packages to build a custom admin panel.

Documentation    Support

Field Types

About field types
Existing Field Types
Custom Field Types

ABOUT FIELD TYPES

Field types are defined in the Controller and settle the way that particular field looks in the add / edit view.

Think of the field type as the type of input:

<input type=”text” />

For some entities, you won't just need text inputs, you'll need datepickers, upload buttons, 1-n relationship, n-n relationships, textareas, etc.

For each of them, you only need to define it properly in the Controller, in the “fields” array. All field types will need at least three things:

  • the name of the column in the database (and the name of the input, implicitly)
  • the human-readable label for the input
  • the type of the input

The following fields are to be used as $field_definition_array inside:

$this->crud->addField($field_definition_array, 'update/create/both');

STANDARD FIELD TYPES

address

Use Algolia Places autocomplete to help users type their address faster. With the store_as_json option, it will store the address, postcode, city, country, latitude and longitude in a JSON in the database. Without it, it will just store the address string.

[   // Address
    'name' => 'address',
    'label' => 'Address',
    'type' => 'address',
    // optional
    'store_as_json' => true
],

Please note

Use attribute casting

For information stored as JSON in the database, it's recommended that you use attribute casting to array or object. That way, every time you get the info from the database you'd get it in a usable format.

browse

Open elFinder and select a file from there.

[   // Browse
    'name' => 'image',
    'label' => 'Image',
    'type' => 'browse'
],

Input preview:

Onlick preview:

base64_image

Upload an image and store it in the database as Base64. Notes:

$this->crud->addField([ // base64_image
    'label' => "Profile Image",
    'name' => "image",
    'filename' => "image_filename", // set to null if not needed
    'type' => 'base64_image',
    'aspect_ratio' => 1, // set to 0 to allow any aspect ratio
    'crop' => true, // set to true to allow cropping, false to disable
    'src' => NULL, // null to read straight from DB, otherwise set to model accessor function
]);

checkbox

Checkbox for true/false.

[   // Checkbox
    'name' => 'active',
    'label' => 'Active',
    'type' => 'checkbox'
],

checklist

```php
[
    'label'     => 'Roles',
    'type'      => 'checklist',
    'name'      => 'roles',
    'entity'    => 'roles',
    'attribute' => 'name',
    'model'     => "Backpack\PermissionManager\app\Models\Role",
    'pivot'     => true,
]);

```

checklist_dependency


// two interconnected entities
'label'             => 'User Role Permissions',
'field_unique_name' => 'user_role_permission',
'type'              => 'checklist_dependency',
'name'              => 'roles_and_permissions', // the methods that defines the relationship in your Model
'subfields'         => [
        'primary' => [
            'label'            => 'Roles',
            'name'             => 'roles', // the method that defines the relationship in your Model
            'entity'           => 'roles', // the method that defines the relationship in your Model
            'entity_secondary' => 'permissions', // the method that defines the relationship in your Model
            'attribute'        => 'name', // foreign key attribute that is shown to user
            'model'            => "Backpack\PermissionManager\app\Models\Role", // foreign key model
            'pivot'            => true, // on create&update, do you need to add/delete pivot table entries?]
            'number_columns'   => 3, //can be 1,2,3,4,6
        ],
        'secondary' => [
            'label'          => 'Permission',
            'name'           => 'permissions', // the method that defines the relationship in your Model
            'entity'         => 'permissions', // the method that defines the relationship in your Model
            'entity_primary' => 'roles', // the method that defines the relationship in your Model
            'attribute'      => 'name', // foreign key attribute that is shown to user
            'model'          => "Backpack\PermissionManager\app\Models\Permission", // foreign key model
            'pivot'          => true, // on create&update, do you need to add/delete pivot table entries?]
            'number_columns' => 3, //can be 1,2,3,4,6
        ],
    ],
],

ckeditor

Show a wysiwyg CKEditor to the user.

[   // CKEditor
    'name' => 'description',
    'label' => 'Description',
    'type' => 'ckeditor',
    // optional:
    'extra_plugins' => ['oembed', 'widget', 'justify']
],

color

[   // Color
    'name' => 'background_color',
    'label' => 'Background Color',
    'type' => 'color'
],

color_picker

Show a pretty colour picker using Bootstrap Colorpicker.

[   // color_picker
    'label' => 'Background Color',
    'name' => 'background_color'
    'type' => 'color_picker',
    'colorpicker_options' => ['customClass' => 'custom-class']
]

custom_html [v2.0.7+]

Allows you to insert custom HTML in the create/update forms. Usually used in forms with a lot of fields, to separate them using h1-h5, hr, etc, but can be used for any HTML.

[   // CustomHTML
    'name' => 'separator',
    'type' => 'custom_html',
    'value' => '<hr>'
],

date

[   // Date
    'name' => 'birthday',
    'label' => 'Birthday',
    'type' => 'date'
],

date_picker

Show a pretty Bootstrap Datepicker.

[   // date_picker
   'name' => 'date',
   'type' => 'date_picker',
   'label' => 'Date',
   // optional:
   'date_picker_options' => [
      'todayBtn' => true,
      'format' => 'dd-mm-yyyy',
      'language' => 'fr'
   ],
],

Please note it is recommended that you use attribute casting on your model (cast to date).

date_range // TODO

datetime

[   // DateTime
    'name' => 'start',
    'label' => 'Event start',
    'type' => 'datetime'
],

Please note: if you're using datetime attribute casting on your model, you also need to place this mutator inside your model:

    public function setDatetimeAttribute($value) {
        $this->attributes['datetime'] = \Date::parse($value);
    }

Otherwise the input's datetime-local formal will cause some errors.

datetime_picker

Show a Bootstrap Datetime Picker.

[   // DateTime
    'name' => 'start',
    'label' => 'Event start',
    'type' => 'datetime_picker',
    // optional:
    'datetime_picker_options' => [
        'format' => 'DD/MM/YYYY HH:mm',
        'language' => 'fr'
    ]
],

Please note: if you're using date attribute casting on your model, you may also need to place this mutator inside your model:

    public function setDatetimeAttribute($value) {
        $this->attributes['datetime'] = \Date::parse($value);
    }

Otherwise the input's datetime-local formal will cause some errors. Remeber to change "datetime" with the name of your attribute (column name).

dropzone // TODO

email

[   // Email
    'name' => 'email',
    'label' => 'Email Address',
    'type' => 'email'
],

enum

Show a select with the values in the database for that ENUM field. Requires that the db column type is "enum". If the db column allows null, the " - " value will also show up in the select.

[   // Enum
    'name' => 'status',
    'label' => 'Status',
    'type' => 'enum'
],

PLEASE NOTE the enum field only works for MySQL databases.

hidden

Include an <input type="hidden"> in the form.

[   // Hidden
    'name' => 'status',
    'type' => 'hidden'
],

icon_picker

Show an icon picker. Supported icon sets are fontawesome, glyphicon, ionicon, weathericon, mapicon, octicon, typicon, elusiveicon, materialdesign as per the jQuery plugin, bootstrap-iconpicker.

The stored value will be the class name (ex: fa-home).

[
    'label' => "Icon",
    'name' => 'icon',
    'type' => 'icon_picker',
    'iconset' => 'fontawesome' // options: fontawesome, glyphicon, ionicon, weathericon, mapicon, octicon, typicon, elusiveicon, materialdesign
],

Your input will look like button, with a dropdown where the user can search or pick an icon:

image

Upload an image and store it on the disk.

Step 1. Show the field.

$this->crud->addField([ // image
    'label' => "Profile Image",
    'name' => "image",
    'type' => 'image',
    'upload' => true,
    'crop' => true, // set to true to allow cropping, false to disable
    'aspect_ratio' => 1, // ommit or set to 0 to allow any aspect ratio
]);

Here's how that looks:

Step 2. Set a mutator on your Model, so that the file can be stored. You can use this boilerplate code and modify it to match your use case:

public function setImageAttribute($value)
    {
        $attribute_name = "image";
        $disk = "public_folder";
        $destination_path = "uploads/folder_1/subfolder_3";

        // if the image was erased
        if ($value==null) {
            // delete the image from disk
            \Storage::disk($disk)->delete($this->image);

            // set null in the database column
            $this->attributes[$attribute_name] = null;
        }

        // if a base64 was sent, store it in the db
        if (starts_with($value, 'data:image'))
        {
            // 0. Make the image
            $image = \Image::make($value);
            // 1. Generate a filename.
            $filename = md5($value.time()).'.jpg';
            // 2. Store the image on disk.
            \Storage::disk($disk)->put($destination_path.'/'.$filename, $image->stream());
            // 3. Save the path to the database
            $this->attributes[$attribute_name] = $destination_path.'/'.$filename;
        }
    }

The uploaded images are not deleted for you

If you delete an entry (using the CRUD or anywhere inside your app), the image file won't be deleted from the disk.

If you're NOT using soft deletes on that Model and want the image to be deleted at the same time the entry is, just specify that in your Model's deleting event:

    public static function boot()
    {
        static::deleting(function($obj) {
            \Storage::disk('public_folder')->delete($obj->image);
        });
    }

month

[   // Month
    'name' => 'month',
    'label' => 'Month',
    'type' => 'month'
],

number

Shows an input type=number to the user, with optional prefix and suffix:

[   // Number
    'name' => 'number',
    'label' => 'Number',
    'type' => 'number',
    // optionals
    // 'prefix' => "$",
    // 'suffix' => ".00",
],

page_or_link

Select an existing page from PageManager or an internal or external link. It’s used in the MenuManager package, but can be used in any other model just as well. Looks like this:

And its definition looks like this:

[   // PageOrLink
    'name' => 'type',
    'label' => "Type",
    'type' => 'page_or_link',
    'page_model' => '\Backpack\PageManager\app\Models\Page'
]

password field

[   // Password
    'name' => 'password',
    'label' => 'Password',
    'type' => 'password'
],

radio

Show radios according to an associative array you give the input and let the user pick from them. You can choose for the radio options to be displayed inline or one-per-line.

[
    'name'        => 'status', // the name of the db column
    'label'       => 'Status', // the input label
    'type'        => 'radio',
    'options'     => [ // the key will be stored in the db, the value will be shown as label; 
                        0 => "Draft",
                        1 => "Published"
                    ],
    // optional
    //'inline'      => false, // show the radios all on the same line?
]

range

[   // Range
    'name' => 'range',
    'label' => 'Range',
    'type' => 'range'
],

select (1-n relationship)

Show a Select with the names of the connected entity and let the user select one of them.
Your relationships should already be defined on your models.

[  // Select
   'label' => "Category",
   'type' => 'select',
   'name' => 'category_id', // the db column for the foreign key
   'entity' => 'category', // the method that defines the relationship in your Model
   'attribute' => 'name', // foreign key attribute that is shown to user
   'model' => "App\Models\Tag" // foreign key model
]

select2 (1-n relationship)

[Works just like the SELECT field, but prettier]

Show a Select2 with the names of the connected entity and let the user select one of them.
Your relationships should already be defined on your models.

[  // Select2
   'label' => "Category",
   'type' => 'select2',
   'name' => 'category_id', // the db column for the foreign key
   'entity' => 'category', // the method that defines the relationship in your Model
   'attribute' => 'name', // foreign key attribute that is shown to user
   'model' => "App\Models\Tag" // foreign key model
]

select_multiple (n-n relationship)

Show a Select with the names of the connected entity and let the user select any number of them.
Your relationships should already be defined on your models.

[       // SelectMultiple = n-n relationship (with pivot table)
    'label' => "Tags",
    'type' => 'select_multiple',
    'name' => 'tags', // the method that defines the relationship in your Model
    'entity' => 'tags', // the method that defines the relationship in your Model
    'attribute' => 'name', // foreign key attribute that is shown to user
    'model' => "App\Models\Tag", // foreign key model
    'pivot' => true, // on create&update, do you need to add/delete pivot table entries?
]

select2_multiple (n-n relationship)

[Works just like the SELECT field, but prettier]

Show a Select2 with the names of the connected entity and let the user select any number of them.
Your relationships should already be defined on your models.

[       // Select2Multiple = n-n relationship (with pivot table)
    'label' => "Tags",
    'type' => 'select2_multiple',
    'name' => 'tags', // the method that defines the relationship in your Model
    'entity' => 'tags', // the method that defines the relationship in your Model
    'attribute' => 'name', // foreign key attribute that is shown to user
    'model' => "App\Models\Tag", // foreign key model
    'pivot' => true, // on create&update, do you need to add/delete pivot table entries?
]

select_from_array

Display a select with the values want:

[ // select_from_array
    'name' => 'template',
    'label' => "Template",
    'type' => 'select_from_array',
    'options' => [‘one’ => ‘One’, ‘two’ => ‘Two’],
    'allows_null' => false,
    // 'allows_multiple' => true, // OPTIONAL; needs you to cast this to array in your model;
],

simplemde

Show a SimpleMDE markdown editor to the user.

[   // SimpleMDE
    'name' => 'description',
    'label' => 'Description',
    'type' => 'simplemde'
],

summernote

Show a Summernote wysiwyg editor to the user.

[   // Summernote
    'name' => 'description',
    'label' => 'Description',
    'type' => 'summernote'
],

table

Show a table with multiple inputs per row and store the values as JSON in the database. The user can add more rows and reorder the rows as they please.

[ // Table
    'name' => 'options',
    'label' => 'Options',
    'type' => 'table',
    'entity_singular' => 'option', // used on the "Add X" button
    'columns' => [
        'name' => 'Name',
        'desc' => 'Description',
        'price' => 'Price'
    ],
    'max' => 5, // maximum rows allowed in the table
    'min' => 0 // minimum rows allowed in the table
],

The end result will look like this:

Cast the attribute as 'object' or 'array' in your model

It's highly recommended that you use attribute casting on your model when working with JSON stored in database columns.

text

The basic field type, all it needs is the two mandatory parameters: name and label.

[ // Text
    'name' => 'title',
    'label' => "Title",
    'type' => 'text',
    // optional
    //'prefix' => '',
    //'suffix' => ''
],

You can use the optional 'prefix' and 'suffix' attributes to display something before and after the input, like icons, path prefix, etc:

textarea

Show a textarea to the user.

[   // Textarea
    'name' => 'description',
    'label' => 'Description',
    'type' => 'textarea'
],

time

[   // Time
    'name' => 'start',
    'label' => 'Start time',
    'type' => 'time'
],

time_picker // TODO

tinymce

Show a wysiwyg (TinyMCE) to the user.

[   // TinyMCE
    'name' => 'description',
    'label' => 'Description',
    'type' => 'tinymce'
],

upload

Step 1. Show a file input to the user:

[   // Upload
    'name' => 'image',
    'label' => 'Image',
    'type' => 'upload',
    'upload' => true,
    'disk' => 'uploads' // if you store files in the /public folder, please ommit this; if you store them in /storage or S3, please specify it;
],

Step 2. In order to save/update/delete the file from disk&db, we need to create a mutator on your model:

public function setImageAttribute($value)
    {
        $attribute_name = "image";
        $disk = "public";
        $destination_path = "folder_1/subfolder_1";

        $this->uploadFileToDisk($value, $attribute_name, $disk, $destination_path);
    }

How it works:

The field sends the file, through a Request, to the Controller. The Controller then tries to create/update the Model. That's when the mutator on your model will run. That also means we can do any file validation (file, image, mimetypes, mimes) in the Request, before the file is stored on the disk.

The uploadFileToDisk() method will take care of everything for most use cases:

/**
     * Handle file upload and DB storage for a file:
     * - on CREATE
     *     - stores the file at the destination path
     *     - generates a name
     *     - stores the full path in the DB;
     * - on UPDATE
     *     - if the value is null, deletes the file and sets null in the DB
     *     - if the value is different, stores the different file and updates DB value
     * /
public function uploadFileToDisk($value, $attribute_name, $disk, $destination_path) {}

If you wish to have a different functionality, you can delete the method call from your mutator and do your own thing.

The uploaded files are not deleted for you

When you delete an entry (wether through CRUD or the application), the uploaded files will not be deleted.

If you're NOT using soft deletes on that Model and want the file to be deleted at the same time the entry is, just specify that in your Model's deleting event:

    public static function boot()
    {
        static::deleting(function($obj) {
            \Storage::disk('public_folder')->delete($obj->image);
        });
    }

upload_multiple

Shows a multiple file input to the user and stores the values as a JSON array in the database.

Step 1. Show a multiple file input to the user:

[   // Upload
    'name' => 'photos',
    'label' => 'Photos',
    'type' => 'upload_multiple',
    'upload' => true,
    'disk' => 'uploads' // if you store files in the /public folder, please ommit this; if you store them in /storage or S3, please specify it;
],

Step 2. In order to save/update/delete the files from disk&db, we need to create a mutator on your model:

public function setPhotosAttribute($value)
    {
        $attribute_name = "photos";
        $disk = "public";
        $destination_path = "folder_1/subfolder_1";

        $this->uploadMultipleFilesToDisk($value, $attribute_name, $disk, $destination_path);
    }

Step 3. Since the filenames are stored in the database as a JSON array, we're going to use attribute casting on your model, so every time we get the filenames array from the database it's converted from a JSON array to a PHP array:

    protected $casts = [
        'photos' => 'array'
    ];

How it works:

The field sends the files, through a Request, to the Controller. The Controller then tries to create/update the Model. That's when the mutator on your model will run. That also means we can do any file validation (file, image, mimetypes, mimes) in the Request, before the files are stored on the disk.

The uploadMultipleFilesToDisk() method will take care of everything for most use cases:

/**
     * Handle multiple file upload and DB storage:
     * - if files are sent
     *     - stores the files at the destination path
     *     - generates random names
     *     - stores the full path in the DB, as JSON array;
     * - if a hidden input is sent to clear one or more files
     *     - deletes the file
     *     - removes that file from the DB.
     * /
public function uploadMultipleFilesToDisk($value, $attribute_name, $disk, $destination_path) {}

If you wish to have a different functionality, you can delete the method call from your mutator and do your own thing.

The uploaded files are not deleted for you

When you delete an entry (wether through CRUD or the application), the uploaded files will not be deleted.

If you're NOT using soft deletes on that Model and want the files to be deleted at the same time the entry is, just specify that in your Model's deleting event:

    public static function boot()
    {
        static::deleting(function($obj) {
            if (count((array)$obj->photos)) {
                foreach ($obj->photos as $file_path) {
                    \Storage::disk('public_folder')->delete($file_path);
                }
            }
        });
    }

url

[   // URL
    'name' => 'link',
    'label' => 'Link to video file',
    'type' => 'url'
],

video

Allow the user to paste a Youtube/Vimeo link. That will get the video information with Javascript and store it as a JSON in the database.

Field definition:

[   // URL
    'name' => 'video',
    'label' => 'Link to video file on Youtube or Vimeo',
    'type' => 'url'
],

An entry stored in the database will look like this:

$video = {
    id: 234324,
    title: ‘my video title’,
    image: ‘https://provider.com/image.jpg',
    url: ‘http://provider.com/video',
    provider: ‘youtube’
}

So you should use attribute casting in your model, to cast the video as array or object.

view

Load a custom view in the form.

[
        'name' => 'custom-ajax-button',
        'type' => 'view',
        'view' => 'partials/custom-ajax-button'
],

Note: the same functionality can be achieved using a custom field type, or using the custom_html field type (if the content is really simple).

week

[   // Week
    'name' => 'first_week',
    'label' => 'First week',
    'type' => 'week'
],

wysiwyg

Show a wysiwyg (CKEditor) to the user.

[   // WYSIWYG Editor
    'name' => 'description',
    'label' => 'Description',
    'type' => 'wysiwyg'
],

CUSTOM FIELD TYPES

The actual field types are stored in the Backpack/CRUD package in /resources/views/fields. If you need to extend the CRUD with a new field type or overwrite an existing field, you don’t need to modify the package, you just need to add a file in your application in /resources/views/vendor/backpack/crud/fields. The package checks there first, and only if there's no file there, it will load it from the package.

Your field definition will be something like:

[
  // Custom Field
  'name' => 'address',
  'label' => 'Home address',
  'type' => 'address'
]);

And your blade file something like:

<!-- field_type_name -->
<div @include('crud::inc.field_wrapper_attributes') >
    <label>{!! $field['label'] !!}</label>
    <input
        type="text"
        name="{{ $field['name'] }}"
        value="{{ old($field['name']) ? old($field['name']) : (isset($field['value']) ? $field['value'] : (isset($field['default']) ? $field['default'] : '' )) }}"
        @include('crud::inc.fieldAttributes')
    >

    {{-- HINT --}}
    @if (isset($field['hint']))
        <p class="help-block">{!! $field['hint'] !!}</p>
    @endif
</div>


@if ($crud->checkIfFieldIsFirstOfItsType($field, $fields))
  {{-- FIELD EXTRA CSS  --}}
  {{-- push things in the after_styles section --}}

      @push('crud_fields_styles')
          <!-- no styles -->
      @endpush


  {{-- FIELD EXTRA JS --}}
  {{-- push things in the after_scripts section --}}

      @push('crud_fields_scripts')
          <!-- no scripts -->
      @endpush
@endif

{{-- Note: most of the times you'll want to use @if ($crud->checkIfFieldIsFirstOfItsType($field, $fields)) to only load CSS/JS once, even though there are multiple instances of it. --}}

You will find everything you need inside the $crud, $entry, and $field variables:

  • $crud - all the crudpanel settings, options and variables;
  • $entry - in EDIT forms, the current entry being modified (the actual values);
  • $field - all options that have been passed for this field;

Field Types