In this section, we have gathered various non-standard approaches to using Select
, which you can modernize for your needs.
Async
The example demonstrates the async
method, but at the same time, we use the approach of working through asyncMethod
, thus saving time on creating a controller and writing the implementation directly in the resource or page:
protected function formFields(): iterable
{
return [
Select::make('Select')->async(
$this->getAsyncMethodUrl('selectOptions'),
)->asyncOnInit(),
]
}
public function selectOptions(): MoonShineJsonResponse
{
$options = new Options([
new Option(label: 'Option 1', value: '1', selected: true, properties: new OptionProperty(image: 'https://cutcode.dev/images/platforms/youtube.png')),
new Option(label: 'Option 2', value: '2', properties: new OptionProperty(image: 'https://cutcode.dev/images/platforms/youtube.png')),
]);
return MoonShineJsonResponse::make(data: $options->toArray());
}
protected function formFields(): iterable
{
return [
Select::make('Select')->async(
$this->getAsyncMethodUrl('selectOptions'),
)->asyncOnInit(),
]
}
public function selectOptions(): MoonShineJsonResponse
{
$options = new Options([
new Option(label: 'Option 1', value: '1', selected: true, properties: new OptionProperty(image: 'https://cutcode.dev/images/platforms/youtube.png')),
new Option(label: 'Option 2', value: '2', properties: new OptionProperty(image: 'https://cutcode.dev/images/platforms/youtube.png')),
]);
return MoonShineJsonResponse::make(data: $options->toArray());
}
protected function formFields(): iterable
{
return [
Select::make('Select')->async(
$this->getAsyncMethodUrl('selectOptions'),
)->asyncOnInit(),
]
}
public function selectOptions(): MoonShineJsonResponse
{
$options = new Options([
new Option(label: 'Option 1', value: '1', selected: true, properties: new OptionProperty(image: 'https://cutcode.dev/images/platforms/youtube.png')),
new Option(label: 'Option 2', value: '2', properties: new OptionProperty(image: 'https://cutcode.dev/images/platforms/youtube.png')),
]);
return MoonShineJsonResponse::make(data: $options->toArray());
}
protected function formFields(): iterable
{
return [
Select::make('Select')->async(
$this->getAsyncMethodUrl('selectOptions'),
)->asyncOnInit(),
]
}
public function selectOptions(): MoonShineJsonResponse
{
$options = new Options([
new Option(label: 'Option 1', value: '1', selected: true, properties: new OptionProperty(image: 'https://cutcode.dev/images/platforms/youtube.png')),
new Option(label: 'Option 2', value: '2', properties: new OptionProperty(image: 'https://cutcode.dev/images/platforms/youtube.png')),
]);
return MoonShineJsonResponse::make(data: $options->toArray());
}
protected function formFields(): iterable
{
return [
Select::make('Select')->async(
$this->getAsyncMethodUrl('selectOptions'),
)->asyncOnInit(),
]
}
public function selectOptions(): MoonShineJsonResponse
{
$options = new Options([
new Option(label: 'Option 1', value: '1', selected: true, properties: new OptionProperty(image: 'https://cutcode.dev/images/platforms/youtube.png')),
new Option(label: 'Option 2', value: '2', properties: new OptionProperty(image: 'https://cutcode.dev/images/platforms/youtube.png')),
]);
return MoonShineJsonResponse::make(data: $options->toArray());
}
Reactive
Select::make('Company', 'company')->options([
1 => 'Laravel',
2 => 'CutCode',
3 => 'Symfony',
])->reactive(function (FieldsContract $fields, mixed $value, Select $ctx, array $values): FieldsContract {
$fields->findByColumn('dynamic_value')?->options((int) $value === 1 ? [
4 => 4,
] : [2 => 2]);
return $fields;
}),
Select::make('Dynamic value', 'dynamic_value')->options([4 => 4])->reactive(),
Select::make('Company', 'company')->options([
1 => 'Laravel',
2 => 'CutCode',
3 => 'Symfony',
])->reactive(function (FieldsContract $fields, mixed $value, Select $ctx, array $values): FieldsContract {
$fields->findByColumn('dynamic_value')?->options((int) $value === 1 ? [
4 => 4,
] : [2 => 2]);
return $fields;
}),
Select::make('Dynamic value', 'dynamic_value')->options([4 => 4])->reactive(),
Select::make('Company', 'company')->options([
1 => 'Laravel',
2 => 'CutCode',
3 => 'Symfony',
])->reactive(function (FieldsContract $fields, mixed $value, Select $ctx, array $values): FieldsContract {
$fields->findByColumn('dynamic_value')?->options((int) $value === 1 ? [
4 => 4,
] : [2 => 2]);
return $fields;
}),
Select::make('Dynamic value', 'dynamic_value')->options([4 => 4])->reactive(),
Select::make('Company', 'company')->options([
1 => 'Laravel',
2 => 'CutCode',
3 => 'Symfony',
])->reactive(function (FieldsContract $fields, mixed $value, Select $ctx, array $values): FieldsContract {
$fields->findByColumn('dynamic_value')?->options((int) $value === 1 ? [
4 => 4,
] : [2 => 2]);
return $fields;
}),
Select::make('Dynamic value', 'dynamic_value')->options([4 => 4])->reactive(),
Select::make('Company', 'company')->options([
1 => 'Laravel',
2 => 'CutCode',
3 => 'Symfony',
])->reactive(function (FieldsContract $fields, mixed $value, Select $ctx, array $values): FieldsContract {
$fields->findByColumn('dynamic_value')?->options((int) $value === 1 ? [
4 => 4,
] : [2 => 2]);
return $fields;
}),
Select::make('Dynamic value', 'dynamic_value')->options([4 => 4])->reactive(),
ShowWhen
Due to the fact that by default ShowWhen
removes hidden elements from the DOM
, we can duplicate several Select
with different values and display them based on a condition.
We added setNameAttribute
to avoid conflict when saving the form.
Select::make('Company', 'company')->options([
1 => 'Laravel',
2 => 'CutCode',
3 => 'Symfony',
]),
Select::make('Dynamic value', 'dynamic_value')
->setNameAttribute('dynamic_value_1')
->showWhen('company', '1')
->options([1 => 1, 2 => 2,]),
Select::make('Dynamic value', 'dynamic_value')
->setNameAttribute('dynamic_value_2')
->showWhen('company', '2')
->options([3 => 3, 4 => 4,]),
Select::make('Company', 'company')->options([
1 => 'Laravel',
2 => 'CutCode',
3 => 'Symfony',
]),
Select::make('Dynamic value', 'dynamic_value')
->setNameAttribute('dynamic_value_1')
->showWhen('company', '1')
->options([1 => 1, 2 => 2,]),
Select::make('Dynamic value', 'dynamic_value')
->setNameAttribute('dynamic_value_2')
->showWhen('company', '2')
->options([3 => 3, 4 => 4,]),
Select::make('Company', 'company')->options([
1 => 'Laravel',
2 => 'CutCode',
3 => 'Symfony',
]),
Select::make('Dynamic value', 'dynamic_value')
->setNameAttribute('dynamic_value_1')
->showWhen('company', '1')
->options([1 => 1, 2 => 2,]),
Select::make('Dynamic value', 'dynamic_value')
->setNameAttribute('dynamic_value_2')
->showWhen('company', '2')
->options([3 => 3, 4 => 4,]),
Select::make('Company', 'company')->options([
1 => 'Laravel',
2 => 'CutCode',
3 => 'Symfony',
]),
Select::make('Dynamic value', 'dynamic_value')
->setNameAttribute('dynamic_value_1')
->showWhen('company', '1')
->options([1 => 1, 2 => 2,]),
Select::make('Dynamic value', 'dynamic_value')
->setNameAttribute('dynamic_value_2')
->showWhen('company', '2')
->options([3 => 3, 4 => 4,]),
Select::make('Company', 'company')->options([
1 => 'Laravel',
2 => 'CutCode',
3 => 'Symfony',
]),
Select::make('Dynamic value', 'dynamic_value')
->setNameAttribute('dynamic_value_1')
->showWhen('company', '1')
->options([1 => 1, 2 => 2,]),
Select::make('Dynamic value', 'dynamic_value')
->setNameAttribute('dynamic_value_2')
->showWhen('company', '2')
->options([3 => 3, 4 => 4,]),
onChangeMethod
This approach allows you to send a request when the main Select
is changed and return the html
for the next Select
, displaying it in the block by selector:
public function selectValues(): MoonShineJsonResponse
{
$options = new Options([
new Option('Option 1', '1', false, new OptionProperty(image: 'https://cutcode.dev/images/platforms/youtube.png')),
new Option('Option 2', '2', true, new OptionProperty(image: 'https://cutcode.dev/images/platforms/youtube.png')),
]);
return MoonShineJsonResponse::make()
->html(
(string) Select::make('Next')->options($options)
);
}
protected function formFields(): iterable
{
return [
Select::make('Select')->options([
1 => 1,
2 => 2,
])->onChangeMethod('selectValues', selector: '.next-select'),
Div::make()->class('next-select'),
];
}
public function selectValues(): MoonShineJsonResponse
{
$options = new Options([
new Option('Option 1', '1', false, new OptionProperty(image: 'https://cutcode.dev/images/platforms/youtube.png')),
new Option('Option 2', '2', true, new OptionProperty(image: 'https://cutcode.dev/images/platforms/youtube.png')),
]);
return MoonShineJsonResponse::make()
->html(
(string) Select::make('Next')->options($options)
);
}
protected function formFields(): iterable
{
return [
Select::make('Select')->options([
1 => 1,
2 => 2,
])->onChangeMethod('selectValues', selector: '.next-select'),
Div::make()->class('next-select'),
];
}
public function selectValues(): MoonShineJsonResponse
{
$options = new Options([
new Option('Option 1', '1', false, new OptionProperty(image: 'https://cutcode.dev/images/platforms/youtube.png')),
new Option('Option 2', '2', true, new OptionProperty(image: 'https://cutcode.dev/images/platforms/youtube.png')),
]);
return MoonShineJsonResponse::make()
->html(
(string) Select::make('Next')->options($options)
);
}
protected function formFields(): iterable
{
return [
Select::make('Select')->options([
1 => 1,
2 => 2,
])->onChangeMethod('selectValues', selector: '.next-select'),
Div::make()->class('next-select'),
];
}
public function selectValues(): MoonShineJsonResponse
{
$options = new Options([
new Option('Option 1', '1', false, new OptionProperty(image: 'https://cutcode.dev/images/platforms/youtube.png')),
new Option('Option 2', '2', true, new OptionProperty(image: 'https://cutcode.dev/images/platforms/youtube.png')),
]);
return MoonShineJsonResponse::make()
->html(
(string) Select::make('Next')->options($options)
);
}
protected function formFields(): iterable
{
return [
Select::make('Select')->options([
1 => 1,
2 => 2,
])->onChangeMethod('selectValues', selector: '.next-select'),
Div::make()->class('next-select'),
];
}
public function selectValues(): MoonShineJsonResponse
{
$options = new Options([
new Option('Option 1', '1', false, new OptionProperty(image: 'https://cutcode.dev/images/platforms/youtube.png')),
new Option('Option 2', '2', true, new OptionProperty(image: 'https://cutcode.dev/images/platforms/youtube.png')),
]);
return MoonShineJsonResponse::make()
->html(
(string) Select::make('Next')->options($options)
);
}
protected function formFields(): iterable
{
return [
Select::make('Select')->options([
1 => 1,
2 => 2,
])->onChangeMethod('selectValues', selector: '.next-select'),
Div::make()->class('next-select'),
];
}
Fragments
Thanks to the fact that Fragment
sends form data along with the request, we can change the set of Select
elements upon reloading the fragment:
protected function formFields(): iterable
{
$selects = [];
$value = request()->integer('_data.first', 1);
if($value === 1) {
$selects[] = Select::make('Second')->options([
1 => 1,
2 => 2,
]);
}
if($value === 2) {
$selects[] = Select::make('Third')->options([
1 => 1,
2 => 2,
]);
}
return [
Fragment::make([
Select::make('First')->options([
1 => 1,
2 => 2,
])->setValue($value)->onChangeEvent(
AlpineJs::event(JsEvent::FRAGMENT_UPDATED, 'selects')
),
...$selects,
])->name('selects'),
];
}
protected function formFields(): iterable
{
$selects = [];
$value = request()->integer('_data.first', 1);
if($value === 1) {
$selects[] = Select::make('Second')->options([
1 => 1,
2 => 2,
]);
}
if($value === 2) {
$selects[] = Select::make('Third')->options([
1 => 1,
2 => 2,
]);
}
return [
Fragment::make([
Select::make('First')->options([
1 => 1,
2 => 2,
])->setValue($value)->onChangeEvent(
AlpineJs::event(JsEvent::FRAGMENT_UPDATED, 'selects')
),
...$selects,
])->name('selects'),
];
}
protected function formFields(): iterable
{
$selects = [];
$value = request()->integer('_data.first', 1);
if($value === 1) {
$selects[] = Select::make('Second')->options([
1 => 1,
2 => 2,
]);
}
if($value === 2) {
$selects[] = Select::make('Third')->options([
1 => 1,
2 => 2,
]);
}
return [
Fragment::make([
Select::make('First')->options([
1 => 1,
2 => 2,
])->setValue($value)->onChangeEvent(
AlpineJs::event(JsEvent::FRAGMENT_UPDATED, 'selects')
),
...$selects,
])->name('selects'),
];
}
protected function formFields(): iterable
{
$selects = [];
$value = request()->integer('_data.first', 1);
if($value === 1) {
$selects[] = Select::make('Second')->options([
1 => 1,
2 => 2,
]);
}
if($value === 2) {
$selects[] = Select::make('Third')->options([
1 => 1,
2 => 2,
]);
}
return [
Fragment::make([
Select::make('First')->options([
1 => 1,
2 => 2,
])->setValue($value)->onChangeEvent(
AlpineJs::event(JsEvent::FRAGMENT_UPDATED, 'selects')
),
...$selects,
])->name('selects'),
];
}
protected function formFields(): iterable
{
$selects = [];
$value = request()->integer('_data.first', 1);
if($value === 1) {
$selects[] = Select::make('Second')->options([
1 => 1,
2 => 2,
]);
}
if($value === 2) {
$selects[] = Select::make('Third')->options([
1 => 1,
2 => 2,
]);
}
return [
Fragment::make([
Select::make('First')->options([
1 => 1,
2 => 2,
])->setValue($value)->onChangeEvent(
AlpineJs::event(JsEvent::FRAGMENT_UPDATED, 'selects')
),
...$selects,
])->name('selects'),
];
}