AlbertLens's avatar

Laravel Nova make dropdown dependant on another dropdown value dynamically. One field depending on another field.

Hello.

Dropdown --> select COMPANY Dropdown --> select Shop (only those of the selected company)

I am creating an app with Laravel Nova and for my users create view I need to choose Company from one dropdown and when that company is selected choose Shop from than company. I have the models and tables for users, companies and shops (a company hasMany shops).

But I need to limit the shops to be selected. If no company is selected, shops should be empty or hidden, and when a company is selected, shops will show to select from all the shops of that company_id,

Any ideas of how to achieve this?

I am using BelonsTo Nova field. Besides, all the belongsTo dependency Nova Packages seem outdated and not working (orlyapps, MANMOHANJIT SINGH, etc.).

Thank you all.

0 likes
5 replies
piljac1's avatar
piljac1
Best Answer
Level 28

What Nova version are you using ? Because in Nova 4 it's easily achievable. I don't have a Nova application on this computer to test the following code, but it should put you on the right track.

// At the top of your file.
use App\Models\Shop as ShopModel;

// In the fields() method.
BelongsTo::make('Company'),

Select::make('Shop')
    ->searchable()
    ->hide()
    ->dependsOn(
        ['company'],
        function (Select $field, NovaRequest $request, FormData $formData) {
            if ($formData->company) {
                $shops = ShopModel::where('company_id', $formData->company)
                    ->get()
                    ->mapWithKeys(fn ($shop) => [
                        // The label here is gonna be on your Nova Shop resource title.
                        // If you don't have a Nova Shop resource
                        // or desire another label, alter this logic.
                        $shop->id => Shop::make($shop)->title()
                    ]);

                $field->options($shops)->show();
            } else {
                $field->options([])->hide();
            }
        }
    ),
2 likes
AlbertLens's avatar

@piljac1 Thank you very much.

It WORKS!!!

I changed the names to Spanish (because my present project is in Spanish) and it is working perfectly.

I have: use App\Models\Tienda as TiendaModel;

BelongsTo::make('Cliente','Cliente')->sortable()->showOnPreview()->required(false)->withoutTrashed(), Select::make('Tienda','tienda_id') ->hide() ->dependsOn( ['Cliente'], function (Select $field, NovaRequest $request, FormData $formData) { if ($formData->Cliente) { $shops = TiendaModel::where('cliente_id', $formData->Cliente) ->get() ->mapWithKeys(fn ($shop) => [ // The label here is gonna be on your Nova Shop resource title. // If you don't have a Nova Shop resource // or desire another label, alter this logic. $shop->id => Tienda::make($shop)->title() ]); $field->options($shops)->show(); } else { $field->options([])->hide(); } } )->onlyOnForms(),

The only thing which is NOT working is the ->hide() and ->show(). The field is always visible, but it is not a problem for me in this project. Maybe in the future.

Again, tks very much for your help.

piljac1's avatar

@AlbertLens Glad I could help! Weird that the show and hide behavior doesn't work though, because I've used a similar logic successfully in the past.

AlbertLens's avatar

@piljac1 Yes. Quite weird. I am using Laravel Nova 4 (last week's version). I have tried with other methods as well, such as ->hideWhenCreating() or ->showOnCreating(), but nothing relevant. It is not working inside the dependsOn() clause.

If I find a solutions, do not hesitate that I will publish it here, too.

Thanks again.

MUNIS's avatar

@piljac1 I tried it for multiselect and worked .Thank you. This is my code :

        Multiselect::make('Employees','employees')
        ->dependsOn(
            ['round'],
            function (Multiselect $field, NovaRequest $request, \Laravel\Nova\Fields\FormData $formData) {
                $emps = Employees::where('round', $formData->round)
                    ->get()
                    ->mapWithKeys(fn ($emps) => [
                        $emps->id => Employee::make($emps)->title()
                    ]);
    
                $field->options($emps)->show();
            }
        ),            // Multiselect::make('Employees','employees')

Please or to participate in this conversation.