Skip to content

Select, Settings, FieldsNames. Empty settings array after merge #2047

Description

@korundKrona

MoonShine Version

4.15

Laravel Version

Other framework

PHP Version

8.2

Database Driver & Version

No response

Description

Bug: FieldsNames settings are discarded by Settings

Select::fieldsNames() passes the FieldsNames values to settings():

public function fieldsNames(FieldsNames $names): static
{
    return $this->settings(array_filter($names->toArray()));
}

When an array is passed to settings(), a new Settings instance is created:

public function settings(array|Settings $settings): static
{
    if (is_array($settings)) {
        $settings = Settings::make($settings);
    }

    $this->settings = array_merge(
        $this->settings,
        $settings->toArray()
    );

    return $this;
}

The problem is that Settings only accepts keys declared in its $values array:

protected array $values = [
    'delimiter' => null,
    'splitOn' => null,
    'diacritics' => null,
    // ...
];

However, FieldsNames provides fields such as:

[
    'valueField' => 'id',
    'labelField' => 'name',
]

Since valueField and labelField are not present in Settings::$values, Settings::fromArray() silently ignores them:

foreach ($values as $name => $value) {
    if (array_key_exists($name, $this->values)) {
        $this->set($name, $value);
    }
}

As a result, Settings becomes empty and the valueField / labelField configuration is lost.

Expected behavior

FieldsNames::make()->value('id')->label('name') should produce:

[
    'valueField' => 'id',
    'labelField' => 'name',
]

and these values should be preserved when passed through settings().

Suggested fix

Add the corresponding keys to Settings::$values:

protected array $values = [
    'valueField' => null,
    'labelField' => null,

    'delimiter' => null,
    'splitOn' => null,
    // ...
];

The important part is that the bug occurs because an array is converted into Settings, and Settings::fromArray() filters unknown keys against $values, thereby dropping all FieldsNames settings.

Workaround

Due to a bug in Settings::fromArray(), FieldsNames cannot currently be passed to settings() as an array.

Instead, I create an empty Settings instance and populate the required fields using set():

$settings = Settings::make([])
    ->set('valueField', 'id')
    ->set('labelField', 'name')
    ->set('searchField', 'name');

->settings($settings)

This works because set() adds the values directly to the internal $values array, bypassing the filtering performed by Settings::fromArray().

The issue can be fixed upstream by adding these fields to Settings::$values or by changing the filtering logic in fromArray().

Select::make('Select')
    ->settings($settings)

Steps To Reproduce

  1. Create search select
  2. Get list with other fields, exmaple: id, name, not label, value

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions