Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel 5.2 update Eloquent Master Detail on same page

Tags:

php

laravel

Here are the two models,blade page and controllers I have for implementing the master-detail page in Laravel 5.2. I would like to know how I can update detail part back to database.

1) Master Model

namespace App;

use Illuminate\Database\Eloquent\Model;

class Order  extends Model
{
    protected $fillable = [
        'id',
        'name',
        'created_at',
        'updated_at'
    ];

    public function detail()
    {
        return $this->hasMany('App\OrderDetail','fid','id');
    }   



    public function getDetailCountAttribute()
    {
        return $this->hasMany('App\OrderDetail','fid','id')->count();
    }       


    public static function boot()
    {
        parent::boot();    

        // cause a delete of a product to cascade to children so they are also deleted
        static::deleted(function($order)
        {
            $order->detail()->delete();
        });
    }    
}

2) Detail Model

namespace App;

use Illuminate\Database\Eloquent\Model;

class OrderDetail extends Model
{
    protected $fillable = [
        'id',
        'oid',
        'item',
        'total',
        'created_at',
        'updated_at'
    ];
}

3) The master detail page (partial), in OrderDetail part, jQuery applied to dynamically add items in the table.

<body>
    <h1>Order Edit</h1>
        {!! Form::model($order,['method' => 'PATCH','route'=>['order.update',$order->id]]) !!}
    <div class="form-group">
        ORDER ID:{{$order->id}}
        <br /><br />
    </div>
    <div class="form-group">
        {!! Form::label('order Name', 'ORDER NAME:') !!}
        {!! Form::text('name',$order->name,['class'=>'form-control']) !!}
    </div>
    <div class="form-group">
     <!--order detail part start-->   

    <br />
    {{ Form::select('productInput', $product,'',['ID'=>'productInput']) }}

    {{ Form::number('productQtyInput','',['class'=>'form-control','style'=>'width:250px','ID'=>'OrderQtyInput']) }}


    {{ Form::button('Add',['onclick'=>'product_add();']) }}

    <br />
    <table class="table table-striped table-bordered table-hover" style="width:30%;" border=1 id="TblOrderList" >
        <thead>
             <tr class="bg-info" id="ingHEADER">
                 <th width=2%>PRODUCTID</th>
                 <th width=5% >PRODUCT</th>
                 <th width=5%>QTY</th>
                 <th width=5% colspan=2>COMMAND</th>
             </tr>
        </thead>
        <tbody>
        </tbody>
    </table>        
     <!--order detail part end-->   
    </div>
    <div class="form-group">
        {!! Form::submit('Update', ['class' => 'btn btn-primary']) !!}
    </div>
    {!! Form::close() !!}
</body>

<script type="text/javascript">
function product_add(){
    var ingID =$( "#productInput").val();
    var ingName =$( "#productInput option:selected").text();
    var ingQty =$("#productQtyInput").val();

    var rowCount = $('#TblOrderList .ingData').length;
    rowCount++;


    var outHTML =
        '<tr class="ingData" id="ingRow' + rowCount + '">'
            + '<td><div id="ingID' + rowCount + '">' + ingID + '</div></td>'
            + '<td><div id="ingName' + rowCount + '">' + ingName + '</div></td>'
            + '<td><input type="number" id="ingQTY' + rowCount + '" value="' + ingQty + '"/></td>'
            + '<td>'
                + '<button class="OrderREMOVE" type="button">DELETE</button>'
                + '<button class="OrderUP" type="button">up</button>'
                + '<button class="OrderDOWN" type="button">down</button>'
            + '</td>'
        + '</tr>';

    $('#TblOrderList tr:last').after(outHTML);
    $('#ingUNIT' + rowCount)
        .find('option[value="' + ingUnit + '"]')
        .prop('selected', 'selected');

}
</script>

4) Finally the update function in OrderController, currently it can update the master part. But I am not sure how to loop each detail and update them in same function.

public function update(Request $request, $id)
{
    //
   $orderUpdate = $request->all();
   $order = Order::find($id);
   $order->update($orderUpdate);


   return redirect('order');        
}
like image 762
mememoremore Avatar asked Mar 26 '16 19:03

mememoremore


Video Answer


1 Answers

You have two options to make that work:

  1. Either you make a request for each OrderDetail item (in this case you have to POST the values via ajax and you can keep your controller code)
  2. Or you make an array of inputs, submit all data at once, and process those inputs on the server.

If you opt for the second option, you'll need to add [] to your input name in order to make that input an array. Actually, you don't even have a name on your input, so your controller will never receive the values of that input, as they are not present on the POST variables.

So you need something like:

<input type="number" name="qty[]" id="ingQTY' + rowCount + '" value="' + ingQty + '"/>

Note to the name="qty[]"

On the controller side, you just need to:

public function update(Request $request, $id)
{
    // Update the order
    $orderUpdate = $request->all();
    $order = Order::find($id);
    $order->update($orderUpdate);

    // Go through all qty (that are related to the details, and create them)
    foreach ($postValues['qty'] as $qty) {

        $order->detail()->create([ 
            'oid' => $order->id,
            'total' => $qty,
        ]);
    }
    return redirect('order');       
}

This should give an idea of what you need. Of course you should probably submit the order detail id and check on the controller if that id exists and only update the detail when that value exists. If it doens't exist, that you create the detail.

I also thing you're missing a few inputs for the order detail (on the javascript part), since the model has a item attribute and you don't seem to create an input for that column.

like image 131
Luís Cruz Avatar answered Sep 20 '22 12:09

Luís Cruz