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

vincej's avatar
Level 15

Can't get a JSON array to display in Select/Option in Blade

Yes, I know this should be straight forward, but I can't get it to work. I have tried every permutation and read SO for hours.

I keep getting this error even though my data is an array:

foreach() argument must be of type array|object, string given

Chrome Dev Tools console.log output:

(3) [{…}, {…}, {…}]
0
{supplier_name: 'Euro Shield', id: 3}
1 
{supplier_name: 'Conico', id: 6}
2 
{supplier_name: 'Enercon Products', id: 1}
length 3
[[Prototype]] 
Array(0)

Ok - so here is an abbreviated version of the code which lead to this result:

JAVASCRIPT:

$.ajax({
                url: "/product_fullsearch/"+product_id,
                dataType: "json",
                type:"GET",
                success: function (data) {
                    var products = data['arr1'];
                    var supplier = data['arr2'];
                    var alt_suppliers = data['arr3'];        //  NB:  This is an array
                    var inventory = data['arr4'];

                   let result = JSON.stringify(alt_suppliers);
                   let altSuppliers = JSON.parse(result ?? '')

                    console.log(altSuppliers);

                    $("#alt_suppliers").val(altSuppliers);
					blah, blah
})

BLADE:

<div>
                <select name="altSuppliers" id="alt_suppliers">
                    @foreach($altSuppliers ?? ' ' as $supplier)
                        <option value="{{$supplier ?? ' '}}">{{$supplier ?? ' '}}</option>
                    @endforeach
                </select>
 </div>

0 likes
10 replies
tykus's avatar

Here is the issue (after all, it is a PHP error message)

@foreach($altSuppliers ?? ' ' as $supplier)

The null coalescing operation ($altSuppliers ?? ' ') gives you a string if the $altSuppliers variable is null or undefined.

I am puzzled to understand how the Javascript and Blade are supposed to be working together??? Are you expecting the AJAX request to somehow provide Blade with an array???

vincej's avatar
Level 15

@tykus thanks for helping out!

If I don't use the the null coalescing operator, I get this error:

Undefined variable $altSuppliers

Essentially yes, I want the Ajax call to provide a series of values which in turn get passed through to the Select in the Blade. The request for the values are the result of a click event.

tykus's avatar

@vincej it cannot work like that. Blade has already been compiled and returned before your JavaScript executes. You cannot pass data from JS into PHP as you are trying.

Better that the AJAX request returns a HTML (Blade-rendered) partial than JSON. You can simply replace or append the response into your HTML

vincej's avatar
Level 15

Ok, I get it.

However, I have several other places in my code where where I have very successfully passed a value from Ajax into PHP. BUT (!) , looking at that code I DID NOT attempt to send through the value until after the blade view had been compiled.

So, using the same view and the same Ajax request as above, I have all these guys, but they are not arrays, just single values:

 success: function (data) {
                    var products = data['arr1'];
                    var supplier = data['arr2'];
                     var inventory = data['arr4'];

And then the blade view is this, NOTE the null value:

<div class="col-md-2">{{ Form::label('product_id', 'Product Code') }}</div>
    		<div class="col-md-4 mb-2">{{ Form::text('product_id', null, ['class'=>'form-control', 'readonly'=>'readonly']) }}</div>

So - bottom line, how do I get this array in there? Just put in a null? BUT then, how do I do that with a foreeach?

 <select name="altSuppliers" id="alt_suppliers">
 @foreach($altSuppliers as $supplier)
                        <option value="{{$supplier}}">{{$supplier ?? ''}}</option>
   @endforeach
                </select>

MANY THANKS!

tykus's avatar

@vincej I don't know how you're currently passing data from JS to PHP; Javascript executes in the Browser while PHP is executed on server, so I can only imagine this is by way of a Request.

In this case, as I mentioned before, you can return rendered HTML rather than JSON whenever you make an AJAX request - appending this HTML to the DOM. Otherwise, you would need to iterate over the JSON building up a similar HTML string (not Blade) which can be appended to the DOM.

vincej's avatar
Level 15

MANY THANKS ! I have taken your advice, and been researching adding an append to my JS, and passing this array into the HTML that way. I was not clear enough in my post of yesterday. I simply want to pass this JSON array into the blade view. Passing a single JS value is easy. Passing an array into a select/option is proving to be more tricky. I will keep hunting.

cheers!

jlrdw's avatar

@vincej if you already have the data and just passing it from controller, you can just foreach to fill the select option.

Just me but I normally like to Json decode first and just work with a regular array.

vincej's avatar
Level 15

@jlrdw thanks for that.

This particular view is pulling in controller/DB data subject to a click event. It then gets passed into the view off of JS.

Snapey's avatar

Hi Vince

Your ajax request can receive from the server, either json array of values, OR formatted html.

If you received formatted html then you could just insert it into the page underneath the right dom node.

If you want it to be json array, you need to iterate over the array in javascript and merge the data into html template fragment and then insert that into the page. The old way of doing this is with string concatenation, but templates make it much easier.

(pretty much what @tykus already advised)

Still, I'd much rather use Livewire than spend ages trying to get javascript to work.

vincej's avatar
vincej
OP
Best Answer
Level 15

@snapey

HI Mark! I agree with you 100%. JS is a pain. However, for me, it is all about the overhead of learning something new. When/if I learn something new, it will likely be Vue3 with Inertia. I seem to have a mental block with LiveWire. Maybe I should look at it again.

Anyway, I have (foolishly) pursued the idea that I could just pass a JSON array to the View, and the select would take care of things. Nope. Following @tykus suggestion to do a JS append I have come up with the below, which to my own amazement is working. I just have to tidy up the View formatting now. I hope this might help someone else:

                    function altSupplier(){
                        var length = alt_suppliers.length;
                        for(var j = 0; j < length; j++)
                        {
                            var newOption = $('<option/>');
                            newOption.text(alt_suppliers[j].supplier_name);
                            newOption.attr('value', alt_suppliers[j].id);
                            $('#alt_suppliers').append(newOption);
                        }
                    }
                    altSupplier();

Please or to participate in this conversation.