Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

theUnforgiven's avatar

Looking for jQuery help....

Hi all,

I have the following jQuery:

(function() {
            $('body').on('change', $(".colors"), function(e) {
                e.preventDefault();
                var option = $(".colors option:selected").val();
                var size = $(this).data('size-id');
                console.log($("#optionID option:selected").val());
                $(".sizes").append("<option value='"+ option +"' name='size'>"+ option +"</option>");

                // Submit on change
                $("#updateOptions").submit(e);

            });
        })();

Then the following select elements:

<select name="colour"
                            class="browser-default colors"
                            data-index="{!! $product->id !!}"
                            id="optionID"
                    >
                        <option value="" disabled selected>Choose a Colour</option>
                        @foreach($colours as $option)
                            <option value="{!! $option->size !!}"
                                    id="optionId"
                                    data-size-id="{!! $option->size !!}"
                            >
                                {!!  $option->colour  !!}
                                @if($option->stock != 0)
                                    ({!! $option->stock !!} in stock)
                                @endif
                            </option>
                        @endforeach
                    </select>
 <select name="size" class="browser-default sizes"></select>

Basically want to get the selected colour then only show the available sizes.

My controller code looks like this (please don't judge this part as the only way I could think of doing it)

$colours = DB::table('product_options')
            ->leftJoin('products', 'product_options.product_id', '=', 'products.id')
            ->where('product_id', $product->product_id)
            ->groupBy('colour')
            ->where('stock', '>', 0)
            ->select('product_options.*')
            ->get();

Any suggestions and help grateful.

Cheers :)

0 likes
27 replies
theUnforgiven's avatar

The $(".sizes").append("<option value='"+ option +"' name='size'>"+ option +"</option>"); part just return the id i.e 1366 but I need it to show the size for this ID has each ID is different and has different sizes, but this needs to show based on previous select menu of the colour.

davorminchorov's avatar

This is how I would do it:

  1. On colour change, I would send an ajax request to the server,
  2. Query the database,
  3. Get the data I need
  4. Display it in the sizes select using JQuery's append() inside the AJAX's success() method .
1 like
theUnforgiven's avatar

Cheers @Ruffles kinda what I was thinking but nice to see someone else advise the same, will give it a try this evening.

theUnforgiven's avatar

So I went with @Ruffles recommendation and I have the following:

$('body').on('change', $("#optionID"), function(e) {
                e.preventDefault();
                var option = $("#optionID option:selected").val();
                var size = $("#optionID option:selected").attr("data-selected-size-id");

                $.ajax({
                    url: "{!! url('getColourSizes') !!}",
                    data: {
                        option_id: option,
                        size_id: size
                    },
                    dataType: "json",
                    success: function(data) {
                        $(".sizes").append("<option value='"+ data +"' name='size'>"+ data +"</option>");
                    }
                });
            });

But now within the $(".sizes").append("<option value='"+ data +"' name='size'>"+ data +"</option>"); the data how do I get the option_id value? I have tried data.option_id but that returns undefined so not sure what the correct syntax should be here.

Any help appreciated.

lindstrom's avatar

You need to loop over data with $.each (something along the lines of this):

$.each(data, function(key, value) {
      options +=   "<option value='"+ value.size +"' name='size'>"+ value.colour +"</option>";
});
$('.sizes').append(options);
1 like
davorminchorov's avatar

What's your response like on the server? did you put the option_id inside a data array?

theUnforgiven's avatar

@Ruffles

public function getColourSizes(Request $request)
    {
        $selection = DB::table('product_options')
                        ->where('id', $request->get('option_id'))
                        ->where('size', $request->get('size_id'))
                        ->first();

        return response()->json($selection);
    }

Should return the first row which is does as an array.

{"id":1368,"product_id":609,"stock_id":1,"size":"20-22","colour":"Red","stock":2}
theUnforgiven's avatar

@lindstrom Cheers, maybe that will work but I forgot to post the server/response stuff so will your suggestion still be valid based on what I've just posted?

davorminchorov's avatar

Nope, it's a single item. Do a console.log(data) to see the output.

lindstrom's avatar
->first();

Missed it @Ruffles. Then @theUnforgiven , you should be able to access it with dot notation. As Ruffles says, do a console.log(data) and use the correct value.

theUnforgiven's avatar

This is what console.log(data) outputs when selecting the colour in the first select menu:

So ideally just populating the second select with the size.

theUnforgiven's avatar

Sorted it @Ruffles @lindstrom

By:

$.ajax({
                    url: "{!! url('getColourSizes') !!}",
                    data: {
                        option_id: option,
                        size_id: size
                    },
                    dataType: "json",
                    success: function(data) {
                        $("#sizes").append("<option value='"+ data.size +"' name='size'>"+ data.size +"</option>");
                    }
                });

dot notation like you guys mentioned, but if I select the other colour it still shows the previous size and it shouldn't has that size isn't available for the newly selected colour and if you try to select the same colour again it adds the size again, so this shouldn't happen either.

VizuaaLOG's avatar

@theUnforgiven Instead of appending the size, can you just replace what is currently inside the select box?

For example

$.ajax({
                    url: "{!! url('getColourSizes') !!}",
                    data: {
                        option_id: option,
                        size_id: size
                    },
                    dataType: "json",
                    success: function(data) {
                        $("#sizes").html("<option value='"+ data.size +"' name='size'>"+ data.size +"</option>");
                    }
                });
1 like
davorminchorov's avatar

OK but I was thinking more like

beforeSend: function() {
    $selectInputSelector.empty();
}.
success: ....

By the way, don't you need more than 1 size for each color? Because you are returning only one size for each color according to your query.

theUnforgiven's avatar

Yes like now @Ruffles I have a dress in red with two different sizes and currently have:

 $.ajax({
                    url: "{!! url('getColourSizes') !!}",
                    data: {
                        option_id: option,
                        colour_id: colour
                    },
                    dataType: "json",
                    success: function(data) {
                        console.log(data);
                        $.each(data, function(key, value) {
                            sizes += "<option value='"+ value.size +"' name='size'>"+ value.size +"</option>";
                        });
                        $(".sizes").html(sizes);

                    }
                });

Which kinda works but is appending all sizes rather than the two sizes for just the red or just the yellow items:

The method now looks like the following also:

public function getColourSizes(Request $request)
    {
        $selections = DB::table('product_options')
                        ->where('product_id', $request->get('option_id'))
                        ->where('colour', $request->get('colour_id'))
                        ->where('stock', '>=', 1)
                        ->get();
        foreach($selections as $selection) {
            Session::put('stock', $selection->stock);
            Session::put('size', $selection->size);
            Session::put('colour', $selection->colour);
        }

        return response()->json($selections);
    }

My table looks like:

theUnforgiven's avatar

So obviously selecting Yellow should only show 12-14 & 18-20 and likewise for the Red one's sizes.

logging shows:

[Object, Object]
0
:
Object
colour
:
"Yellow"
id
:
1366
product_id
:
609
size
:
"12-14"
stock
:
1
stock_id
:
1
__proto__
:
Object
1
:
Object
colour
:
"Yellow"
id
:
1367
product_id
:
609
size
:
"18-20"
stock
:
1
stock_id
:
2

And unable to select any other option other than the first size.

theUnforgiven's avatar

.append() .html() .prepend() I have tried all 3 and it keep's adding more to the list rather than showing the actual sizes.

simondavies's avatar

ok try the following, ou need to clear the previous entries etc

    success: function(data) {
                    var sizes ='';
                    $.each(data, function(key, value) {
                        sizes += "<option value='"+ value.size +"' name='size'>"+ value.size +"</option>";
                    });
                    $(".sizes").html(sizes);

                }

Notice the reset of the SIZE var var sizes =''; becasue if your not resetting your browser that var will always appends to its self etc so clear it on select before the loop. Also be a little patient as it can take a little while for others o read throw things and others might have logged off :-)

theUnforgiven's avatar

@simondavies Thanks for this, I'll give it a try, for the time been I have done the following:


$(function(){

            $('.colors').on('change', function(e){
                var option = $("#optionID option:selected").val();
                var colour = $("#optionID option:selected").attr("data-selected-colour");
                var select = $(".sizes");

                $.get('/getColourSizes?option_id=' + option + '&colour_id=' + colour, function(data){
                    select.empty();
                    $.each(data, function(index, subcatObj){
                        select.append('<option value="'+subcatObj.size+'">'+subcatObj.size+'</option>');
                    });
                });
            });
            var a = new Array();
            $(".sizes").children("option").each(function(x){
                test = false;
                b = a[x] = $(this).val();
                for (i=0;i<a.length-1;i++){
                    if (b ==a[i] && b != '') test =true;
                }
                if (test) $(this).remove();
            });
        });

Which works in the exact same way as I described, but I will try with jQuery in the original post I made.

Please or to participate in this conversation.