Search code examples
phplaravelmodal-dialoglaravel-bladeadminlte

Make bootstrap modal create an object to be added to list


In my Laravel project, I have the following models:

  • Product ('name' string, 'amount' integer and 'price' decimal)
  • Cart ('cost' decimal)
  • CartProd ('unit_price' decimal, 'amount' integer, 'discount' decimal, 'total_cost' decimal and foreign keys to a product and a cart)

The idea is that, when you want to create a new cart, the CartController method creates a list of all the products, a brand new cart and an empty list in which the selected products for the cart will be added, and sends them all through the view's compact.

public function create(Request $request)
{
    $product_list = Product::all();
    $empty_cart = new Cart();
    $selected_products = array();
    return view('models.carts.create', compact('product_list','empty_cart','selected_products'));
}

public function store(Request $request){}

The view where this happens has the list where the selected products will be shown and a button to add a product to the list.

create.blade.php:

@extends('adminlte::page')
@section('content')

<div class="container"><div class="row justify-content-center"><div class="col-md-8"><div class="card">
    <div class="card-header">
        <h3 class="card-title"> New Cart </h3>
        <div class="card-tools">
            <a class="btn btn-success btn-tool" href="#" data-toggle="modal" data-target="#add">
                <i class="fas fa-plus"></i> Add Product
            </a>
        </div>
    </div><div class="card-body">
        <table class="table table-striped projects table-sm">
            <thead><tr><th>#</th><th>Name</th><th>Unit Cost</th><th>Amount</th><th>Discount</th><th>Final Cost</th><th></th></tr></thead>
            <tbody>
                @forelse($selected_products as $prodCart)
                <tr>
                    <td>{{ $loop->iteration  }}</td>
                    <td>{{ $prodCart->product->name  }}</td>
                    <td>{{ $prodCart->product->price  }}</td>
                    <td>{{ $prodCart->amount  }}</td>
                    <td>{{ $prodCart->discount  }}</td>
                    <td>{{ $prodCart->cost  }}</td>
                    <td>
                        <a class="btn btn-danger btn-circle btn-sm" href="#" data-target="#delete">
                            <i class="fa fa-trash"></i>
                        </a>
                    </td>
                </tr>
                @empty
                <tr><td colspan="7">Empty Cart</td></tr>
                @endforelse
            </tbody></table></div>
    <div class="card-footer">
        @if(!empty($selected_products))
        <button class="btn btn-success" href="send $selected_products to CartController's store method" > Buy Cart </button>
        @endif
</div></div></div></div></div>

@include('models.carts.add')

@endsection

@section('scripts')

@stop

The 'Add Product' button toggles a modal which has the displayed list of products, plus the 'amount' and 'discount' number inputs to create a CartProd with, and the button to actually add them to the list.

add.blade.php:

<!--Modal add -->
<div class="modal fade" id="add" tabindex="-1" role="dialog" aria-hidden="true"><div class="modal-dialog modal-lg"><div class="modal-content">
    <div class="modal-header bg-dark">
        <h5 class="modal-title" id="exampleModalLabel">Add Product to Cart</h5>
        <span class="badge badge-danger" class="close" data-dismiss="modal" aria-label="Close">
            <i class="fas fa-times fa-lg" style="color:#fff"></i>
        </span>
    </div>
    <div class="modal-body">
        <table class="table table-striped projects table-sm">
            <thead><tr><th>#</th><th>Name</th><th>Amount</th><th>Price</th><th>Added</th><th>Discount</th><th>Amount</th><th>Add</th></tr></thead>
            <tbody>
                @forelse($product_list as $product)
                <tr>
                    <td>{{ $loop->iteration  }}</td>
                    <td>{{ $product->name  }}</td>
                    <td>{{ $product->amount  }}</td>
                    <td>{{ $product->price  }}</td>
                    <td>{{ $product->created_at  }}</td>
                    <td><input type="number" name="discount" id="discount" min="0" max="100" size="3" value="0"></td>
                    <td><input type="number" name="amount" id="amount" min="1" max="{{$product->amount}}" size="3" value="1"></td>
                    <td>
                        <a class="btn btn-info btn-circle btn-sm" data-datos="{{$product}}">
                            <i class="fa fa-plus"></i>
                        </a>
                    </td>
                </tr>
                @empty
                <tr>
                    <td>No Products Available.</td>
                </tr>
                @endforelse
            </tbody>
        </table>
</div></div></div></div>

Here are the issues:

  • I haven't found the way to create this new CartProd instance within the modal, and send it back to the list of selected products.
  • How to delete said CartProd if adding it was a mistake.
  • How to update the selected product list every time a new product is added/deleted.
  • The 'Buy Cart' button to send me to the store method of the controller (where all the fancy stuff will be done to save the list of products.)

Thank you so much for your help!


Solution

  • You can create this model with livewire if you are familiar which has all the answers to your issues

    First, wrap the modal fields with a form element

    //Your modal
    <form action="{{route('your_route'}}" method="post">
       @csrf
       <input type="number" name="discount" id="discount" min="0" max="100" size="3" value="0">
       <input type="number" name="amount" id="amount" min="1" max="{{$product->amount}}" size="3" value="1">
        <a class="btn btn-info btn-circle btn-sm" data-datos="{{$product}}" type="submit">
           <i class="fa fa-plus"></i>
        </a>
    </form>
    

    In the controller method you can redirect back to your create.blade.php with a message and the list will refresh.

    public function store(Request $request)
    {
      // your saving logic
      return redirect()->route('your_create_route')
                       ->with('success', 'Added successfully');
    }
    

    As your question is too broad you can trigger a delete action with actioning a button by passing the product ID to delete. This is a custom approach from this. Normally you delete with the laravel's delete method @method('delete') and a POST method.

    // delete link
    <a href="{{route('delete_route', $product->id)}}">
          Delete 
    </a>
    
    // web.php
    Route::get('delete/{id}','YourController@destroy')->name('delete_route');