October CMS resources and help articles

Simple and to the point. Optimized by the community.

Add custom form fields/options to a File attachment

3
by adam, last modified on March 6th, 2020

Create a Acme\Plugin\Models\FileOption model (with a db table) then add a $belongsTo relation to it:

    public $belongsTo = [
        'file' => \System\Models\File::class
    ];

In the plugin boot method, add a $hasOne relationship for the File model:

        File::extend(function ($model) {
            $model->hasOne['file_option'] = [
                \Acme\Plugin\Models\FileOption::class,
                'key' => 'system_file_id'
            ];

            // create the relation otherwise the file fields (title, description) 
            // aren't saved if the extended fields are empty
            $model->bindEvent('model.beforeCreate', function() use ($model) {
                $model->file_option = new \Acme\Plugin\Models\FileOption;
            });
        });

Extend the File backend form with the fields you wish to add (also in the boot() method):

Event::listen('backend.form.extendFields', function ($widget) {

            if (!$widget->model instanceof \System\Models\File) return;

            if (!$widget->getController() instanceof \Acme\Plugin\Models\YourModel) return;

            $widget->addFields([
                'file_option[color]' => [
                    'label' => 'Color',
                    'type' => 'colorpicker',
                ],
                // ... other fields
            ]);
        });

One problem I've noticed is that if any of the extended fields were empty the title and description field weren't saved upon change.

The solution for now was to create the relationship at file upload hence the code

$model->bindEvent('model.beforeCreate', function() use ($model){
    $model->file_option = new \Acme\Plugin\Models\FileOption;
});

And for existing files I has to run this code once :

Event::listen('backend.form.extendFields', function ($widget) {
     foreach (File::get() as $file) {
        if ($file->file_option === null) {
            $file->file_option = new \Acme\Plugin\Models\FileOption;
            $file->save();
        }
    }
});

Discussion

1 comment

0
mmoollllee
Post on July 22nd, 2023 9:42 PM

This way it works by storing the colorpicker field directly within the system_files table:

Plugin.php

use Event;
use System\Classes\PluginBase;
use System\Models\File;

class Plugin extends PluginBase
{
    public function boot()
    {

        Event::listen('backend.form.extendFields', function ($widget) {

            if (!$widget->model instanceof File) return;

            $widget->addFields([
                'color' => [
                    'label' => 'Color',
                    'type' => 'colorpicker',
                ]
            ]);

        });
    }
}

updates/add_color_column_to_system_files.php

use Schema;
use October\Rain\Database\Schema\Blueprint;
use October\Rain\Database\Updates\Migration;

class AddColorColumnToSystemFiles extends Migration
{
    public function up()
    {
        Schema::table('system_files', function (Blueprint $table) {
            $table->string('color')->nullable();
        });
    }

    public function down()
    {
        Schema::table('system_files', function ($table) {
            $table->dropColumn([
                'color'
            ]);
        });
    }
}
We use cookies to measure the performance of this website. Do you want to accept these cookies?