Jaaayz
Jaaayz

Reputation: 1563

Laravel dynamic dropdown not being empty

My goal is to achieve an dynamic dropdown that will display the value of the second dropdown base on the first dropdown.

A service has many categories and a category belongs to a service so the second dropdown is the category and the first dropdown is the service. When the service is selected it will show all the category based on the service selected.

Here is the code in RequestController.php

public function create()
    {
        $client = Client::all()->sortBy('client_name', SORT_NATURAL | SORT_FLAG_CASE)->pluck('client_name', 'id');
        $services = Service::with('categories')->get()->sortBy('code', SORT_NATURAL | SORT_FLAG_CASE)->pluck('description', 'id');
        $categories = Categories::with('service')->get()->sortBy('name', SORT_NATURAL | SORT_FLAG_CASE)->pluck('name', 'id');

        return view('encoder-dashboard.analysis-request.create', compact('client', 'services', 'categories'));
    }

in my fields.blade.php

<!-- Service Id Field -->
<div class="form-group col-sm-6">
    {!! Form::label('service_id', 'Service:') !!}
     {!! Form::select('service_id', $services, null, ['class' => 'form-control','required'])!!}
</div>

<!-- Categories Id Field -->
<div class="form-group col-sm-6">
    {!! Form::label('category_id', 'Category:') !!}
     {!! Form::select('category_id', $categories, null, ['class' => 'form-control','required'])!!}
</div>

The script for handling the request

<script>
        $(function() {
            $('select[name=service_id]').change(function() {

                var url = '{{ url('service') }}' + $(this).val() + '/categories/';

                $.get(url, function(data) {
                    var select = $('form select[name= category_id]');

                    select.empty();

                    $.each(data,function(key, value) {
                        select.append('<option value=' + value.id + '>' + value.name + '</option>');
                    });
                });
            });
        });
    </script>

The route web.php

Route::get('service/{service}/categories', 'ServiceController@getCategories');

And in the ServiceController.php

public function getCategories($service)
{
    $service = Service::findOrFail($service);
    return $service->categories->pluck(['id','name']);
}

I achieved to get all the data using the pluck. But it empty's the form for the category with the name of category_id

So I guess my problem is within the script or nah?

Appreciate if someone could help. Thanks in advance.

Upvotes: 0

Views: 676

Answers (2)

Dimitri Mostrey
Dimitri Mostrey

Reputation: 2355

Try this, I have something similar and there are some small differences.

<script>
    JQuery(function() {
        $('#service_id').change(function() {

            var url = '{{ url('service') }}' + $(this).val() + '/categories/';

            $.get(url, function(data) {
                var select = $('form select[name= category_id]');

                select.empty();

                $.each(data,function(key, value) {
                    select.append('<option value=' + key + '>' + value + '</option>');
                });
            });
        });
    });
</script>

Reverse id and name. First the value is selected, the key is optional (your id). See also Laravel Collections pluck Edit: pluck does not hold an array.

 public function getCategories($service)
{
    $service = Service::findOrFail($service);
    return $service->categories->pluck('name', 'id');
}

Upvotes: 1

Watercayman
Watercayman

Reputation: 8178

,I'm not totally sure what the issue is, but it sounds like it is correctly clearing the data from the select, but not putting it back?

Could be a problem with appending to a changed element, or not properly finding the selector, or maybe it's not dynamic and losing its hook after changing on.('change') vs .change()... (or several things).

Here is a function I use to repopulate. I add the html in the loop and then change the entire select in one go using the hook to $(this) and then trigger the change.

Perhaps this might help you:

// After filtering (any select box across the program), repopulate it -- same function for anything
function ajaxFilterSuccess(typeClass, newArray){
$('.'+typeClass).each(function(i, obj) {

    // Only add Please Select to single selects (not multiple / select2) since multis are usually
    // many to many pivots without a way to mutate the input away from '' (needs to be null or stopped totally)
    if(typeof this.attributes['multiple'] == 'undefined')
        var list = '<option value="">Please Select</option>';

    if ($(this).val() != null) {
        $(this).children(':selected').each(function() {
            // Use native JS to get 'this', so it doesn't confuse with the $(this) selector looping
            list += '<option value="'+this.value+'" selected>'+this.text+'</option>';
        });
    }

    $(this).empty();

    $.each(newArray, function(value,key) {
        list += "<option value='" +value + "'>" + key + "</option>";
    });

    $(this).html(list);
    $(this).trigger('change');
});
}

Upvotes: 0

Related Questions