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

ollie_123's avatar

Another Pivot Table Issue

Hi All

This seems to be the topic of the week lol.

I'm still trying to figure out this pivot table scenario with orders and products and i think i've got it sussed. Except the fact that i cant insert data into the tables due to Call to a member function orders() on null.

I have a pivot table called order_product of which has the columns order_id & product_id.

In my models i have:

Order model: belongsToMany products

public function products()
    {
        return $this->belongsToMany(Product::class);
    }

Product model belongsToMany orders

public function orders()
    {
        return $this->belongsToMany(Order::class);
    }

In the controller, when i $request-> the data and create a record in the orders table it works. However when i added the attach method i getCall to a member function orders() on null Please can someone tell me where i'm going wrong"-

Controller

$form_data = array(

'product_id' => $request->input('option_id'), // this is to accept the product_id checkboxes in an array.
'make'            => $request->make,
'mdl'             => $request->mdl,
'mdl_year'        => $request->mdl_year,
'engine'          => $request->engine,
'transmission'    => $request->transmission,
  );

        Order::create($form_data);

        $order = \App\Order::find('id');
        $order->orders()->attach('product_id');
        
        return redirect.......

Please can someone tell me where i'm going wrong as i've tried many different ways and i've been stuck on this for nearly a week.

Thank you in advance.

0 likes
33 replies
ignium's avatar

It looks like you are trying to call for the orders related to the order with $order->orders()->attach('product_id) which is a relationship that isn't defined. If what you actually are intending to do is to attach a product then you would need to call $order->products()->attach('product_id')

Attaching Many-to-Many

ETA: link to docs

ollie_123's avatar

@ignium thanks for your response.

you're absolutely right. I think i stared at it too long to see lol.

However even when i change to: $order->products()->attach('product_id') i get: Call to a member function products() on null

ignium's avatar

That error means that $order isn't being found in the line above. There's a couple of things I notice:

  • First, you should be passing an actual id to the find() method. In the code above, you are passing the string 'id'. And unless you are hard coding an order with an id that equals the string id, this will fail to pull the correct order.
  • Second, the same goes for the attach function, you either need to be passing a variable (e.g. ($order->products()->attach($product_id);) OR and actual value (I would avoid this way of doing it) (e.g. ($order->products()->attach(2);).

In this case, for the attach, it seems like you'd be passing $form_data['product_id'] to the attach function, but I don't see where you define what the order id would be in the code above

ollie_123's avatar

Hey @ignium

Thanks for your feedback.

In regards to obtaining the ID, could i use a last inserted id function? I'm struggling to get my head round this pivot table thing and how to insert the correct data into the pivot table.

In your 2nd point, i could assign a variable to the request such as $product = 'product_id' => $request->input('option_id'), but i feel as though this would do more harm than good as it would be taking it as a string?

ignium's avatar
ignium
Best Answer
Level 21

One page, I reference constantly to remember relationships, is this one: Laravel: Understanding Eloquent Relationships... with drawings!

I think the simplest way for you to obtain the order would be to just save it to a variable (Model::create() returns an instance of the model created), so it would looks something like this:


$order = Order::create($form_data);

//$order = \App\Order::find($id) <-- This line is no longer needed
$order->products()->attach($form_data['product_id']);

I'm not sure what your Order migration looks like, but it shouldn't have a product id column on it at all, and you shouldn't have to pass the ids to the Order::create() method. Instead, that is taken care of with the call to attach().

Let's assume you have an Order with an id of 2 and the order consists of products with ids of [5, 6, 7]. The $order->products()->attach([5, 6, 7]) call will create three rows in the product_order table (assuming products with those IDs are already in the products table:

  • id: 1 order_id: 2 product_id: 5
  • id: 2 order_id: 2 product_id: 6
  • id: 3 order_id: 2 product_id: 7

When you call $order->products Laravel will query the rows in the product_order table that match the id of the order (in this case 2) and then query the products matching the product_id column in those rows.

1 like
ollie_123's avatar

Hey @ignium. You are a total legend. Thank you. If i could buy you a beer, i would buy you many lol.

Thank you for the resource also. That makes a lot of sense. I guess i was just overcomplicating it.

I still think there's some witchcraft in there as i don't get how it knows which column to put the order_id & the product_id in but it works.

In regards to calling the data, currently, i have a table which when the user clicks to view the record, it takes the id of the row, opens the modal and the data is called via a resource route to the controller to fetch the data and return the values into the input fields based on their id.

<script>
  /* When click edit user */
  $('body').on('click', '#edit', function () {
      var readAction_id = $(this).data('id');
      $.get('readAction/' + readAction_id +'/edit', function (data) {
         $('#modal-two').html("");
          $('#show-modal').modal('show');
          $('#readAction_id').val(data.id);
          $('#make').val(data.make);
          $('#mdl').val(data.mdl);
          $('#mdl_year').val(data.mdl_year);
          $('#engine').val(data.engine);
          $('#transmission').val(data.transmission);
        //   console.log(data.id);
      })
   });
</script>

My question is, to call this data, in my controller i put

        $filereqP = Order::where('user_id', $authUid)->where('stage', 'pending')->with('products')->get();

and passed this to my view. Then in my view i have

            <div class="row">
                            @foreach($filereqP as $order)
                                <div class="col-sm-4">
                                    <small>{{ $order->product_name}} £{{ $order->product_sale}} </small>
                                </div>
                            @endforeach
                        </div><!-- end row -->

however only the £ is outputted twice to the modal for the products but no product name. Now is this because its not being picked up by the JS and displaying the data inside the modal or is it that my syntax is incorrect?

I really appreciate your help dude.

1 like
ignium's avatar

Glad I could offer some help! Regarding the view, I'm not 100% certain, but I think it's probably returning null when accessing the attributes. (I'm kind of going in blind without knowing the structure of the models). My assumption is that instead of calling @foreach($filereqP as $order) you should be calling @foreach($filereqP->products as $product). This will loop through the products and pull their properties in the view like $product->name.

If this view can show multiple orders, you may need to nest another @foreach() within the first, like this.

...
@foreach($filereqP as $order)  {{-- loops through each order --}}
   @foreach($order->products as $product)  {{-- loops through each product in an order --}}
        <div class="col-sm-4">
            <small>{{ $product->name }} £{{ $product->sale }}</small>
        </div>
    @endforeach
@endforeach
...

Any relationship created on a model has both an attribute and a method that returns the actual relationship. In this case it would be $order->products for the attribute (which returns a collection of product models associated with the order) and the method would be $order->products() which would return a BelongsToMany relationship instance.

ollie_123's avatar

Hey @ignium. You definitely have.

So essentially the view page shows a table of which is populated by all of the records with a status of pending. When i click to view the record, the data is populated into a modal via the JS script in my previous post.

I think the bit i'm struggling to get my head round is that inside the modal, i only need to loop through the products for that order but if i use

@foreach($filereqP->products as $product)

i get

Property [products] does not exist on this collection instance.

or if i use

                @foreach($filereqP->order->products as $product)
                                    <div class="col-sm-4">
                                        <small>{{ $product->product_name }} £{{ $product->sale }}</small>
                                    </div>
                                @endforeach

then i get

Property [order] does not exist on this collection instance.

however if i use

@foreach($filereqP as $order) 
                            @foreach($order->products as $product)
                                    <div class="col-sm-4">
                                        <small>{{ $product->name }} £{{ $product->sale }}</small>
                                    </div>
                                @endforeach
                            @endforeach

then it returns 6 x £ when i know that there should only be 3 product values from the pivot table associated with this record.

Sorry for the 1001 questions dude.

ignium's avatar

The top one (@foreach($filereqP->products as $product)) won't work because the query you have written is returning a collection of orders. I was originally thinking the $filereqP variable only contained a single order.

The second one (@foreach($filereqP->order->products as $product)) won't work for the same reason. When you use ->get() on your query, it's returning an instance of Illuminate\Database\Eloquent\Collection, so using @foreach is already looping through the orders (and there is no relationship $order->orders().

The last one with the nested loops should work, maybe $filereqP contains two orders instead of one? Your query is asking to return all orders for a user with a state of "pending".

If you want to peek into what's going into the modal, for a GET request you can access the route directly by typing the url into the browser. If this is the way you go, in the controller, instead of returning a view just dd() what would have been returned as data to the view. If it's a POST request that pulls the data, you might want to use something like Laravel Telescope, which will show you all of the requests (plus other great info).

I should also note, since I don't know exactly what your models look like, the suggestion I had regarding calling $product->name is assuming the product models contain a name attribute (either with as a getter, or as a column in the database), if this isn't the case this will still return null and thus be blank in the view.

A completely tangent sidenote, when using dd() I always add the following line above it (dump('Line '.__LINE__.' in '.__FILE__); otherwise I sometimes forget where I kill the program and then I have to track it down.

ollie_123's avatar

Hey @ignium

I see what you mean. You're absolutely right $filereqP is returning all orders with a status of pending. With this i pass the variable to the view then into the table and display the data in the table like this:-

<div class="tab-content">
                    <div id="pending" class="tab-pane active">
                        <table class="table table-dark table-no-more table-bordered table-striped mb-0 text-center table-sm">
                            <thead>
                                <tr>
                                    <th scope="col">Make</th>
                                    <th scope="col">Model</th>
                                    <th scope="col">Year</th>
                                    <th scope="col">Engine</th>
                                    <th scope="col">Gearbox</th>
                                    <th scope="col">Action</th>
                                </tr>
                            </thead>
                             <tbody>
                                @foreach($filereqP as $pending)
                                    <td data-title="Make">{{ $pending->make }}</td> 
                                    <td data-title="Model" class="capi">{{ $pending->mdl }}</td>
                                    <td data-title="Year">{{ $pending->mdl_year }}</td>
                                    <td data-title="Engine">{{ $pending->engine }}</td>
                                    <td data-title="Gearbox">{{ $pending->transmission }}</td>
                                    <td>
                                        <a href="javascript:void(0){{ $pending->id }}" id="edit" data-toggle="modal" data-target="#modal-two" data-id="{{ $pending->id }}" class="btn btn-sm btn-outline-light"><i class="fa fa-eye"></i></a>
                                    </td>
                                </tr>
                                @endforeach
                            </tbody>
                        </table>
                    </div><!-- end displayed pane -->

Then then when i click the view button it fires up the modal.

Your 1st & second point make sense. Thats why the @foreach($filereqP as $order) is pulling 6 null values because that's the total no of records in the pivot table and therefore in my foreach its calling on all of the records for all of the orders and displaying null as i assume it cant determine which order to call them against.

What would you suggest the best way to call the product data for the specific order record inside of the modal? Should i create a separate variable in the controller and call then ID of the modal record opened?

If it helps this is the query in the controller

$filereqP = Order::where('user_id', $authUid)->where('stage', 'pending')->with('products')->get();

Thank you again for this.

ollie_123's avatar

Hey @ignium

So i've made some progress, although the bit i'm stuck on is how to pass the ID of the record in the modal to the query in the controller.

So in controller i've got:

$orders = Order::find('12')->products()->orderBy('product_sale')->get();

However hardcoding the order id isn't ideal.

and in my view i have

            <div class="row">
                        @foreach($orders as $product) 
                                <div class="col-sm-4">
                                    <small> {{ $product->product_name }} £{{ $product->product_sale }}</small>
                                </div>
                            @endforeach
                        </div><!-- end row -->

So my question is, how do i pass the ID to the query inside of the modal so that it only returns the product data related to that order.

ignium's avatar

It looks like you're already passing the order id through the url (/readAction/{{order}}/edit) in javascript, is this somewhere you could use route model binding?

If that's the case, then you wouldn't even need the query at all.

ollie_123's avatar

Thanks @ignium. So i took your advice & used route model binding, the good news is that the product data for the order is passed to the modal (confirmed in the browser console) however the bad news is, is i'm not sure about how to display the data. If i use a @foreach loop i get undefined variables which makes sense as the $readAction variable is declared after the ``return view``` statement however i'm not sure how to pass the Json product data as a foreach in the modal.

In the controller, the data is called via

public function edit($id)
    {
        $where = array('id' => $id);
        $readAction  = Order::where($where)->first();
        $readAction->load('products');
        
        return Response::json($readAction);
    }

Please can you advise the best course of action to output the data in the view.

Thank you in advance.

ignium's avatar

Hey @oli_d111

Using route model binding in conjunction with method injection would clean up your controller action.

If the route is set up in your routes file, the way I think it is; something to the effect of

Route::get('/readAction/{{order}}/edit', 'YourController@edit');

then your controller function can look something like this:

public function edit(Order $order)
{
    $order->load('products');  // See note 1 below

    return compact('order');
}
  1. Since this is a single relationship on a single model, this may not be necessary. When you call the a property from the relationship, it will add it to the model and call from that each time.

Then in your view, you would call

@foreach($order->products as $product)

I'm not in front of a terminal right now, so I can't test it out, but the return statement might be incorrect in my controller example though. I'm pretty sure directly returning something, returns JSON by default, but I don't remember if you need to use compact() to assign the $order variable in to the view.

ollie_123's avatar

Hey @ignium

Thanks for your suggestion. Unfortunately my edit function is called after return view. I probably should have included the JS in my last post. Apologies.

So when the row edit button is clicked in the view, its taking the id of the row and calls the data via the JS to the edit function in the controller. The edit function then takes all the data where the ID matches and passes it back ti the view via JSON & populates the modal with the data. The bit i'm stuck on is how to pass the product data from Json into the view. I tried using an input field with an ID of products but nothing showed.

This makes sense as technically in the console i'm displaying an array. So the bit i'm stuck on is how to pass the json array into the modal. I know the products for that record are populating as i can see them in the console.

View:

            <div class="row">
                            <div class="col-sm-4">
                                <label>Make</label>
                                <input type="text" readonly class="form-control" name="make" id="make">
                            </div><!-- end col -->
                            <div class="col-sm-3">
                                <label>Model</label>
                                <input type="text" readonly class="form-control capi" name="mdl" id="mdl">
                            </div><!-- end col -->
                            <div class="col-sm-2">
                                <label>Engine</label>
                                <input type="text" readonly class="form-control" name="engine" id="engine">
                            </div><!-- end col -->
                            <div class="col-sm-3">
                                <label>Year</label>
                                <input type="text" readonly class="form-control" name="mdl_year" id="mdl_year">
                            </div><!-- end col -->
                        </div><!-- end row -->

            <div class="row">
                            <div class="col-sm-12">
                                <p>Products:</p>
                            </div><!-- end col -->
                            <div  class="col-sm-3">
                                <!-- <div id="products" ></div> -->
                            </div>
                        </div><!-- end row -->

<script>
  /* When click view open modal */
  $('body').on('click', '#edit', function () {
      var readAction_id = $(this).data('id');
      $.get('readAction/' + readAction_id +'/edit', function (data) {
          $('#edit-modal').modal('show');
          $('#readAction_id').val(data.id);
          $('#make').val(data.make);
          $('#mdl').val(data.mdl);
          $('#mdl_year').val(data.mdl_year);
          $('#engine').val(data.engine);
          $('#transmission').val(data.transmission);
          $('#products').val(data.products);
          console.log(data.products);
      })
   });
</script>

Route:

Route::resource('readAction', 'Customer\VehicleController');

Controller:

public function edit($id)
    {
        $where = array('id' => $id);
        $readAction  = Order::where($where)->first();
        $readAction->load('products');
        
        return Response::json($readAction);
    }

The good news is i can see the products loaded for the record in the console but the difficulty i'm having is displaying that in the view. All of the other inputs are populated based on the ID of the input matching the data form the JS.

Console data when i open a record:

(3) [{…}, {…}, {…}]
0: {id: 1, product_name: "Product One", product_cost: "0", product_sale: "0", status: "Displayed", …}
1: {id: 3, product_name: "Product Two", product_cost: "0", product_sale: "10", status: "Displayed", …}
2: {id: 7, product_name: "Product Three", product_cost: "0", product_sale: "0", status: "Displayed", …}
length: 3

Thanks dude.

ignium's avatar

I put together a repo for you, but I haven't used jQuery in a while, and never with Laravel, so my solution is a little janky.

https://github.com/ignium559/modal-test

There are some migrations and seeders so if you clone the repo then run:

php artisan migrate:fresh --seed

3 sample orders each with 3 products will be populated in the database.

Instead I use the fetch API with a Bootstrap modal. You can click the "Show products" button in each row to load the info into the modal, but then you have to click the "Show" button to show the modal. But everything seems to work.

I precompile the view and replace the HTML in the modal. This is based on Caleb Porzio's Laracasts video Server-Fetched Partials.

Hope this helps, let me know if you have any questions. And if this is way off base, no worries, it was a good exercise for me as well.

ollie_123's avatar

Hey @ignium.

Thank you for putting that together, i really appreciate it. I cloned the repo & had a look however its not quite what i'm looking to do. However a nugget of info i am taking is the @forelse. That is awesome. ;)

I feel like i'm so close to solving it. After reading around today i feel like i just need to decode the object and turn it into an array in the view.

I've tried a couple of different things but this is the furthest i've got:-

Modal Snippet:

<form method="post" action="{{ route('readAction.edit', $pending->id) }}">

            <div class="row">
                            <div class="col-sm-12">
                                <p>Optional Extras:</p>
                            </div><!-- end col -->
                            <div class="col-sm-12">
                            <input type="text" class="form-control" id="products">
                            </div>
                        </div><!-- end row -->

//Script Snippet... 

          $('#products').val(data.products);
          console.log(data.products);
          document.getElementById('products').innerHTML = products.toString();
      })
   });
</script>

Controller:

public function edit($id)
    {
        $where = array('id' => $id);
        $readAction  = Order::where($where)->first();
        $readAction->load('products');
        
        return Response::json($readAction);
    }

Route:

Route::resource('readAction', 'Customer\VehicleController');

This is putting [object Object],[object Object],[object Object] into the input in the modal which is great but how do i convert that to a string array?

Thank you in advance.

ignium's avatar

Is [object Object],[object Object],[object Object] literally what you're getting or are you just simplifying an array of 3 objects?

I totally misunderstood what you were going for a couple of posts back. I think if you're getting the array of objects you mentioned a while ago, something like:

0: {id: 1, product_name: "Product One", product_cost: "0", product_sale: "0", status: "Displayed", …}
1: {id: 3, product_name: "Product Two", product_cost: "0", product_sale: "10", status: "Displayed", …}
2: {id: 7, product_name: "Product Three", product_cost: "0", product_sale: "0", status: "Displayed", …}

I would construct an element for each product and then replace the innerHMTL of the #products element.

I created a sample JSFiddle as an example (again, in vanilla JS).

Injecting innerHTML can leave you susceptible to XSS, so make sure you sanitize the user input first!

If I'm way off base let me know :)

ollie_123's avatar

Hey @ignium.

Yeah, i was literally getting [object Object],[object Object],[object Object] back in the input field.

Awesome thank you for putting that together dude. Very kind of you. I'll admit, my JS knowledge isn't quite there yet so i'm trying to figure this out.

I'm just trying to wrap my head round it and modify to fit the call for products. In the modal, i have set the div id as products. And in the JS i have the following:-

<script>
  /* When click edit user */
  $('body').on('click', '#edit', function () {
      var readAction_id = $(this).data('id');
      $.get('readAction/' + readAction_id +'/edit', function (data) {
          $('#edit-modal').modal('show');
          $('#readAction_id').val(data.id);
          $('#make').val(data.make);
          $('#mdl').val(data.mdl);
          $('#mdl_year').val(data.mdl_year);
          $('#engine').val(data.engine);
          $('#transmission').val(data.transmission);
          $('#products').val(data.products);
          console.log(data.products);
        //   document.getElementById('products').innerHTML = products.toString();
        
        function createElements(arr) 
        {
            let elements = ''
            arr.forEach(function(el) {
            elements += createDiv(el);
            })
            return elements
        }
        function createDiv(data) 
        {
            return `
                <div class="badge-primary">
                <p>${data.products}</p>
                </div>
            `;
        }
        function click(event) 
        {
            event.preventDefault();
            // let elements = createElements(objects);
            document.getElementById('products').innerHTML = elements;
        }

      })
   });
</script>

However i think as its looking for a click event on the last function its not loading the data? Or am i missing something else?

Separately, in terms of XSS & sanitisation, would i still need to clean the inputs even if the user must be authenticated to access this page?

As always thank you in advance. I think i've moved from beer tokens to owing you a crate ;)

ignium's avatar

The click(event) function wouldn't apply in this case, that was just to trigger the event, you're already doing that with .on('click', ....

As for the modifying it to fit to your case, I think you can instead build the html string with the response from your ajax call and then replace the html of <div id="products"></div> (instead of replacing the value of the div).

Something along these lines:

<script>
  $('body').on('click', '#edit', function () {
    var readAction_id = $(this).data('id');
    $.get('readAction/' + readAction_id +'/edit', function (data) {
        $('#edit-modal').modal('show');
        $('#readAction_id').val(data.id);
        $('#make').val(data.make);
        $('#mdl').val(data.mdl);
        $('#mdl_year').val(data.mdl_year);
        $('#engine').val(data.engine);
        $('#transmission').val(data.transmission);

        let htmlString = createElements(data.products);  //Build HTML string with data.products
        $('#products').html(htmlString);  //Replace HTML of products div with the new HTML
        
        function createElements(arr) {
            let elements = ''
            arr.forEach(function(el) {
                elements += createDiv(el);
            })

            return elements
        }

        function createDiv(data) {
            return `
            <div class="badge-primary">
                <p>${data.products}</p>
            </div>
            `;
        }
});
</script>

As far as XSS, a good rule of thumb is to never trust user generated data and sanitize everything a user touches. Even if they're authenticated something could still happen by accident.

But in the grand scheme of things, it's really up to you how strict you want to be with it. I think jQuery might have some sanitation built into it (but I'm not certain) and you're pulling the information from the server (just make sure it's escaped before going into the database), so you're probably ok here.

ollie_123's avatar

Hey @ignium

Ah that makes sense, that was what i thought with the click event but wasn't 100% sure.

Thank you for this. I will look into sanitising aswell.

Out of curiosity, do you know what would cause the output to be undefined undefined undefined in the modal? I know that there are 3 products associated to this record but can't work out why its displaying as undefined?

Thanks in advance.

ignium's avatar

In my sample I call ${data.products} this probably isn't in your product model. Whatever is between the back ticks in the createDiv() function is what's going to be inserted for an individual product. However you want to display that and with whatever properties you're trying to display should replace that section.

ollie_123's avatar

Hey @ignium. I see what you're saying but the bit that confuses me is that i can see the products relevant to that order being called in the console. Also the number of products related to that order produces the same amount of undefined strings in the modal.

In my product model i've got

public function orders()
    {
        return $this->belongsToMany(Order::class);
    }

In the order model i've got

public function products()
   {
       return $this->belongsToMany(Product::class);
   }

& in the controller i've got

public function edit($id)
    {
        $where = array('id' => $id);
        $readAction  = Order::where($where)->first();
        $readAction->load('products');
        
        return Response::json($readAction);
    }

And just for good measure the script in the blade file



        $('#make').val(data.make);
        $('#mdl').val(data.mdl);
        $('#mdl_year').val(data.mdl_year);
        $('#engine').val(data.engine);
        $('#transmission').val(data.transmission);
        $('#products').val(data.products);
        console.log(data.products);

        let htmlString = createElements(data.products);  //Build HTML string with data.products
        $('#products').html(htmlString);  //Replace HTML of products div with the new HTML
        
        function createElements(arr) 
        {
            let elements = ''
            arr.forEach(function(el) 
            {
                elements += createDiv(el);
            })
            return elements
        }

        function createDiv(data) 
        {
            return `
            <div class="badge">
                <p>${data.products}</p>
            </div>
            `;
        }
    })
});
</script>

I'm sorry if I'm missing something super obvious.

ignium's avatar

If you're getting [object Object] in the console, you're not getting a JSON object returned to you. Try just returning the response directly

return $readAction;

I believe that gets encoded as JSON behind the scenes. You're looking for something that looks like the other response you were getting

0: {id: 1, product_name: "Product One", product_cost: "0", product_sale: "0", status: "Displayed", …}
1: {id: 3, product_name: "Product Two", product_cost: "0", product_sale: "10", status: "Displayed", …}
2: {id: 7, product_name: "Product Three", product_cost: "0", product_sale: "0", status: "Displayed", …}

If that doesn't work, I would post a new question, since I'm not super confident in returning JSON responses and someone more helpful in this category might respond. Kind of like the blind leading the blind here :)

ollie_123's avatar

Hey @ignium no worries at all. I appreciate your help in getting me this far. Thanks again 👍🏻

ollie_123's avatar

Hey @ignium if I’m getting undefined undefined undefined in the console would this be down to the

let elements = ‘’
ignium's avatar

It shouldn't be. That's just initially setting the elements variable to an empty string, and then immediatly after that, the forEach() loop appends to it the result of the createDiv() function (once for each object passed in the arr argument, which would be the products property of the ajax call result). If you use Dev Tools to inspect the modal, you should see a <div class="badge"></div> for each product. But if you're getting [object Object...] as the result of the ajax call, then you won't be able to access the properties of the the products so, ${data.products} would be undefined.

What do you get if you console.table(data) before $(#edit-modal').modal('show')?

Also, I don't think this will fix it, but you're manipulating the div#products twice, you can remove the line

$('#products').val(data.products);

because you are doing the actual manipulation with

$('#products').html(htmlString);
ollie_123's avatar

I get all of the order data outputted to the console including all of the product data.

Also you’re right. I thought the same so I changed the ID of the div in the modal to “options” so it could differentiate.

ignium's avatar

To be clear, are you trying to populate a text input? If so, which property do you want to display in the text input? I think I went off on a tangent trying to display each product as a div.

If you're adding a whole product object into the value of the input, then it would show up in the input as [object Object], you'd need to pick which property of the object to add like product.product_name.

I updated the JSFiddle to demonstrate this.

You wrote "input" like 20 times. Geez ignium read!

ollie_123's avatar

Individual divs work for me 👍🏻

In an ideal situation I would like to output an individual div for each product name and its relevant price in an array.

At this stage it’s so that the user can see what products they’ve ordered. Later down the road I will be doing something similar but with invoices.

Next

Please or to participate in this conversation.