mafortis
mafortis

Reputation: 7128

Laravel dropdown gets all options even if not selected

I have drop-down where i show my products attributes, and no matter if i select any option or not it will add all the options to my cart under selected product.

what i need is to just get selected options or leave it empty if nothing has selected.

here is my blade code:

<tbody>
  @foreach($options as $optiontitle => $optioncollection)
  <tr>
    <td style="width: 150px;">{{ $optiontitle }}</td>
    <td class="text-left">
      <select name="attr" class="form-control">
       <option value="">Select</option>
       @foreach($optioncollection as $suboption)
         <option value="{{$suboption->id}}">{{$suboption->title}} - {{ number_format($suboption->price, 0) }}</option>
       @endforeach
      </select>
    </td>
  </tr>
  @endforeach
</tbody>

here is my controller method for attributes which i call them option

$options = $product->suboptions->mapToGroups(function ($item, $key) {
  return [$item->option->title => $item];
});

and this is my cart method where thing happen and everything will be add to cart instead of selected only.

public function addingItem(Request $request, $id)
    {
      $product = Product::where('id', $id)->firstOrFail();

      $customAttributes = [];
      if(!empty($product->suboptions)){
          foreach($product->suboptions as $subs) {
              array_push($customAttributes, [
                  'attr' => [
                      'label' => $subs->title,
                      'price' => $subs->price,
                  ]
              ]);
          }
      }
      Cart::add(array(
        'id' => $product->id,
        'name' => $product->title,
        'price' => $product->price,
        'quantity' => $request->input('quantity'),
        'attributes' => $customAttributes,
      ));
      Session::flash('success', 'This product added to your cart successfully.');
      return redirect()->back();
    }

UPDATE

What I need to get is options title and price (take a look at my order sample to see why and where I need those)

"[{\"id\":29,\"name\":\"effewf\",\"price\":24524,\"quantity\":1,\"attributes\":[{\"attr\":{\"label\":\"Gray\",\"price\":\"7000.00\"}},{\"attr\":{\"label\":\"Red\",\"price\":\"5000.00\"}},{\"attr\":{\"label\":\"15\\\"\",\"price\":\"500000.00\"}},{\"attr\":{\"label\":\"17\\\"\",\"price\":\"700000.00\"}},{\"attr\":{\"label\":\"22\\\"\",\"price\":\"900000.00\"}}],\"conditions\":[]}]"

As you see in my attributes part I have nested array such as :

\"attributes\":[{\"attr\":{\"label\":\"Gray\",\"price\":\"7000.00\"}},....

here is where I get that label and price in my function loop.

If I use loop such as:

foreach($request->attr as $subs) {
  array_push($customAttributes, [
   'attr' => [
    'label' => $subs->title,
    'price' => $subs->price,
    ]
]);

Instead of what I have I will get this error:

Trying to get property of non-object

on this line:

  'attr' => [
    'label' => $subs->title,
    'price' => $subs->price,

PS: If I use $customAttributes = $request->attr; with my own loop (at the top) I will get id of selected option only, which is no good to me.

Upvotes: 2

Views: 2647

Answers (3)

Amr Berag
Amr Berag

Reputation: 1108

Shouldn't you get the options from an order or The Request and not from the Prodect ?!
Because the product should obviously have all options.
...........

-Edit:1

Change your loop like this

foreach($request->attr as $subs)

and change your selct tag to look something like this

<select multiple>

-Edit2

After editing your question, I think you have two options:

  1. use the id from each $subs to query your suboptions again from the DB

OR

  1. Serialize the title and price in the front end html option tag so that you will end up with something like this:

    <option   value="{{$suboption->title.','.$suboption->price}}" .....> .....</option>
    

then inside your loop do like this:

foreach($request->attr as $subs) {
    $title_and_price = explode(',', $subs);
    array_push($customAttributes, [
    'attr' => [
    'label' => $title_and_price[0],
     'price' => $title_and_price[1]
   ]
]);

-Edit:3

We should also add square brackets to the name in the select tag like this:

  <select name="{{ $optiontitle }}[]"  multiple>

Edit:4 I found another problem:

you should use name = "{{ $optiontitle }}[]" in the select because they canot all have the same name thus, you have to make the name attribute of the select tag dynamic as well

Upvotes: 1

Praneeth Nidarshan
Praneeth Nidarshan

Reputation: 1704

Try replacing Controller Function addingItem with below

public function addingItem(Request $request, $id)
    {
      $product = Product::where('id', $id)->firstOrFail();

      $customAttributes = [];
      if(!empty($product->suboptions)){
          foreach($product->suboptions as $subs) {
              array_push($customAttributes, [
                  'attr' => [
                      'label' => $subs->title,
                      'price' => $subs->price,
                  ]
              ]);
          }
      }
      Cart::add(array(
        'id' => $product->id,
        'name' => $product->title,
        'price' => $product->price,
        'quantity' => $request->input('quantity'),
        'attributes' => $request->input('attr'), // Attributes Array
      ));
      Session::flash('success', 'This product added to your cart successfully.');
      return redirect()->back();
    }

I assume you need to insert multiple attributes by

@foreach($options as $optiontitle => $optioncollection)

replace the blade code,

<tbody>
  @foreach($options as $optiontitle => $optioncollection)
  <tr>
    <td style="width: 150px;">{{ $optiontitle }}</td>
    <td class="text-left">
      <select name="attr" class="form-control">
       <option value="">Select</option>
       @foreach($optioncollection as $suboption)
         <option value="{{$suboption->id}}">{{$suboption->title}} - {{ number_format($suboption->price, 0) }}</option>
       @endforeach
      </select>
    </td>
  </tr>
  @endforeach
</tbody>

with below

<tbody>
  @foreach($options as $optiontitle => $optioncollection)
  <tr>
    <td style="width: 150px;">{{ $optiontitle }}</td>
    <td class="text-left">
      <select name="attr[]" class="form-control">
       <option value="">Select</option>
       @foreach($optioncollection as $suboption)
         <option value="{{$suboption->id}}">{{$suboption->title}} - {{ number_format($suboption->price, 0) }}</option>
       @endforeach
      </select>
    </td>
  </tr>
  @endforeach
</tbody>

it will create an attribute array which will prevent the error,

Trying to get property of non-object

If you need further assistance, leave a comment.

Upvotes: 0

Dexter Bengil
Dexter Bengil

Reputation: 6625

Because you called your product's suboptions relationship instead of getting it from the request. You are calling it with this $product->suboptions instead of getting it from the request.

$customAttributes = $request->attr; // try to dd($customAttributes) so you can see it

UPDATE:

You only need to pass the id to your options

<select name="attr[]" class="form-control" multiple>
   <option value="">Select</option>
   @foreach($optioncollection as $suboption)
     <option value="{{$suboption->id}}">{{$suboption->title}} - {{ number_format($suboption->price, 0) }}</option>
   @endforeach
</select>

and in your Controller, fetch them and validate

public function addingItem(Request $request, $id)
{
    $product = Product::findOrFail($id);

    $customAttributes = [];
    if (!empty($request->attr)) {
        foreach ($request->attr as $sub) {
            // You should fetch the price from the database NOT from the user 
            //   request as it will be very vulnerable to attacks

            // find the suboption
            $sub = Suboption::find($sub); // Here I assume you have the Model 
                                    // for your Product's suboptions
            if (!empty($sub->id)) {
                array_push($customAttributes, [
                    'attr' => [
                        'label' => $sub->title,
                        'price' => $sub->price,
                    ]
                ]);
            }
        }
    }

    Cart::add(array(
        'id' => $product->id,
        'name' => $product->title,
        'price' => $product->price,
        'quantity' => $request->input('quantity'),
        'attributes' => $customAttributes,
    ));

    Session::flash('success', 'This product added to your cart successfully.');
    return redirect()->back();
}

Upvotes: 4

Related Questions