platform icon indicating copy to clipboard operation
platform copied to clipboard

ENUM fields with forms Select inputs

Open grinkevich opened this issue 6 months ago • 4 comments

Describe the bug

When you have a proper casting set up in the model with an ENUM field, form fields may experience issues with rendering such fields, even when you pass $options as an array.

For example: File: resources / views / vendor / platform / fields / select.blade.php : 14 Error: Cannot use object of type App\Enums\EnumType as array

To Reproduce Steps to reproduce the behaviour:

  1. You have a model with an enum field cast, for example something like that:
    protected $casts = [
        'enabled' => 'boolean',
        'type' => EnumType::class,
        'provider' => EnumProvider::class,
        'rules' => 'array',
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
    ];
  1. Plus, you have an options() method that will return a prepared key-label array for select input. That is a sort of workaround to make "options" for the Select input. For example:
namespace App\Enums;

enum EnumType: string
{
    case TEXT = 'text';
    case NUMBER = 'number';
    case PRICE = 'price';

    /**
     * Get a label
     */
    public function label(): string
    {
        return match ($this) {
            self::TEXT => __('Text'),
            self::NUMBER => __('Numeric'),
            self::PRICE => __('Price'),
        };
    }

    /**
     * Get all available types as an array
     */
    public static function options(): array
    {
        $options = collect(self::cases())
            ->mapWithKeys(fn($case) => [$case->value => $case->label()])
            ->toArray();

        return $options;
    }
  1. Then you create a select field on the form:
Select::make('enum_type')
    ->required()
    ->title('Enum Type')
    ->empty(__('Select type'))
    ->options(EnumType::options())
    ->help(__('Enum typed options list from the model')),

Expected behaviour A select element that will have options pre-selected based on the Enum type of field. P.S. Additionally, the desired behaviour is to pass just the Enum class as options, and it will render options for that.

Server (please complete the following information):

  • Platform Version: 14.52
  • Laravel Version: 12.18
  • PHP Version: 8.4

grinkevich avatar Jun 21 '25 16:06 grinkevich

For now, the solution I came up with is to edit the select template and add Enum type checks for the current option as the $value variable loads as an Enum type. And second addition is to avoid "empty()" param, which adds value with an empty $key to not throw an error as well.

@component($typeForm, get_defined_vars())
    <div data-controller="select"
        data-select-placeholder="{{$attributes['placeholder'] ?? ''}}"
        data-select-allow-empty="{{ $allowEmpty }}"
        data-select-message-notfound="{{ __('No results found') }}"
        data-select-allow-add="{{ var_export($allowAdd, true) }}"
        data-select-message-add="{{ __('Add') }}"
    >
        <select {{ $attributes }}>
            @foreach($options as $key => $option)
                <option value="{{$key}}"
                        @isset($value)
                            @if (is_array($value) && in_array($key, $value)) selected
                            @elseif ($value instanceof \UnitEnum && $value->value === $key) selected
                            @elseif (!($value instanceof \UnitEnum) && isset($value[$key]) && $value[$key] == $option) selected
                            @elseif ($key == $value) selected
                            @endif
                        @endisset
                >{{$option}}</option>
            @endforeach
        </select>
    </div>
@endcomponent

grinkevich avatar Jun 21 '25 16:06 grinkevich

I think this can be simplified by using the ->fromEnum() method, which is specifically designed for cases like this.

Here's an example from the Orchid tests: https://github.com/orchidsoftware/platform/blob/ba754210adb0045046769987b78652a23e84a935/tests/Unit/Screen/Fields/SelectTest.php#L271-L280

tabuna avatar Jun 24 '25 06:06 tabuna

Interesting, I wasn't aware of that functionality already in place! Is it worth adding to the Example screens or documentation? Correct me if I am wrong, but this seems to be undocumented functionality 🤔 https://orchid.software/en/docs/field/#select

P.S. seem like we can close this as there is a solution for Enums :)

grinkevich avatar Jun 24 '25 13:06 grinkevich

I believe this might be useful to have in the documentation. Would it be possible to add an example?

tabuna avatar Jun 25 '25 07:06 tabuna