2
I have a dynamically generated table where I insert several products. I’m trying to use a for to save these products, but if I only have one product doesn’t work anymore, you need to have more than one. I tried with foreach but it didn’t work.
View:
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row">
<div class="col-md-12">
<form method="post" action="{{ route('storeProduct') }}">
{{ csrf_field() }}
<div class="panel panel-default">
<div class="panel-heading">Dashboard</div>
<div class="panel-body">
<table class="table m-0" id="products-table">
<thead>
<tr>
<th>Produto/Serviço</th>
<th>Quantidade</th>
<th>Valor Unitário</th>
<th>Valor Total</th>
<th>Remover</th>
</tr>
</thead>
<tbody class="row">
</tbody>
<tfoot>
<tr>
<td colspan="5" style="text-align: left;">
<button class="btn btn-info waves-effect w-md waves-light m-b-5" onclick="AddTableRow()" type="button">Adicionar Produto</button>
</td>
</tr>
</tfoot>
</table>
<button class="btn btn-primary" type="submit">Incluir Orçamento</button>
</div>
</div>
</form>
</div>
</div>
</div>
@endsection
@push('js')
<script>
RemoveTableRow = function(handler) {
var tr = $(handler).closest('tr');
tr.fadeOut(400, function() {
tr.remove();
});
return false;
};
AddTableRow = function() {
var newRow = $("<tr>");
var cols = "";
cols += '<td class="col-md-4"><input type="text" class="form-control product" name="name[]"></td>';
cols += '<td class="col-md-2"><input type="text" class="form-control amount" name="amount[]"></td>';
cols += '<td class="col-md-2"><input type="text" class="form-control price" name="unit_price[]"></td>';
cols += '<td class="col-md-2 total"><input readonly type="text" class="form-control" name="total_price[]"></td>';
cols += '<td class="col-md-2">';
cols += '<button class="btn btn-danger waves-effect w-md waves-light m-b-5" onclick="RemoveTableRow(this)" type="button">Remover</button>';
cols += '</td>';
newRow.append(cols);
$("#products-table").append(newRow);
$(".amount, .price").unbind('blur keyup');
$(".amount, .price").on("blur keyup",function(){
const tr = $(this).parent().parent();
const quant = parseInt(tr.find('.amount').val());
const valor = parseInt(tr.find('.price').val());
var total = quant * valor;
if (!isNaN(quant) && !isNaN(valor)){
tr.find('.total').html('<input readonly type="text" class="form-control" name="total_price[]" value=" '+total+' ">');
}
});
return false;
};
</script>
@endpush
$request:
array:5 [▼
"_token" => "wLRaFmgHxEMtOzPMzzylPFjtJLawgr262kOz4xGf"
"name" => array:2 [▼
0 => "Produto 1"
1 => "Produto 1"
]
"amount" => array:2 [▼
0 => "2"
1 => "3"
]
"unit_price" => array:2 [▼
0 => "200"
1 => "300"
]
"total_price" => array:2 [▼
0 => "400"
1 => "900"
]
]
Controller:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Product;
class ProductsController extends Controller
{
private $product;
public function __construct(Product $product)
{
$this->product = $product;
}
public function store(Request $request)
{
for ($i = 0; $i < count($request->all()); $i++) {
$this->product = new Product();
$this->product->name = $request->name[$i];
$this->product->amount = $request->amount[$i];
$this->product->unit_price = $request->unit_price[$i];
$this->product->total_price = $request->total_price[$i];
$this->product->save();
}
}
}
In the controller use
for ($i = 0; $i < count($request->name); $i++)
– Ennio Sousa
Yes, I ended up putting it that way. But is this the best way to do it? I wouldn’t have any way of doing it without knowing the name of the camp?
– Marcelo
The best is not to use
<input name="total_price[]">
, but yes<input name="product[1][total_price]">
where this Indice 1 is inserted dynamically by javascript. When in the loop useforeach()
instead offor()
– Ennio Sousa