I have a table of items:
As you can see, there is a warehouse area since I am working with an inventory system where an item can be stored in one or more warehouses, and depending on the warehouse, the available stock is different. My goal is that when I select the warehouse in the select, the stock that that item has available within the selected warehouse is shown to me, and while in the first one it works for me, in any other row it does not. And if, in addition, I click on 'add' later it does not continue to do the function, nothing appears. Could you help me?
This is my function:
$(".js-agregar").on("click", function(){
fila = $(this).closest("tr");
agregar(fila);
});
var cont = 1;
total = 0;
$("#guardar").hide();
$(".js-almacen-id").change(mostrarValores);
function mostrarValores() {
datosProducto = document.getElementById('almacen_id').value.split('_');
$("#stock").val(datosProducto[1]);
};
var almacen_id = $('.js-almacen-id');
almacen_id.change(function(event) {
const index = $(event.target).attr('index')
var articulo_id = $(event.target).attr('.js-articulo-id')
$.ajax({
url: "{{ route('get_products_by_id') }}",
method: 'GET',
data: {
almacen_id: event.target.value,
},
success: function(data) {
$(".js-stock").eq(index).val(data.disponible);
$(".js-almacen-id").eq(index).val(data.almacen_id);
$(".js-articulo-id").eq(index).val(data.articulo_id);
}
});
});
And my add to cart function:
function agregar(fila) {
articulo_id = fila.find(".js-articulo-id").val();
articulo = fila.find(".js-articulo-nombre").val();
cantidad = fila.find(".js-cantidad").val();
almacen_id = fila.find(".js-almacen-id").val();
stock = $("#stock").val();
if (articulo_id != "" && cantidad != "" && cantidad > 0 && articulo_id != null) {
if (parseInt(stock) >= parseInt(cantidad)) {
subtotal[cont] = cantidad * precio_compra;
total = total + subtotal[cont];
var fila = '<tr class="selected" id="fila' + cont +
'"><td><button type="button" class="btn btn-danger btn-sm" onclick="eliminar(' + cont +
');"><i class="fas fa-trash-alt"></i></button></td><td><input type="hidden" name="articulo_id[]" value="' +
articulo_id + '">' + articulo +
'</td><td> <input type="hidden" name="almacen_id[]" value="' + almacen_id +
'"> <input class="form-control" type="number" value="' + almacen_id +
'" disabled> </td><td> <input type="number" class="form-control" name="cantidad[]" value="' + cantidad +
'"></td> <td><input type="text" name="comentario[]" class="form-control" required></td></tr>';
cont++;
limpiar();
totales();
evaluar();
$('#detalles').append(fila);
} else {
Swal.fire({
icon: 'error',
cancelButtonColor: '#d33',
text: 'La cantidad a vender supera el stock.',
})
}
} else {
Swal.fire({
icon: 'error',
cancelButtonColor: '#d33',
text: 'Rellene todos los campos del detalle del pedido.',
})
}
}
And so is the get_products_by_id
in my item controller:
public function get_products_by_id(Request $request)
{
if ($request->ajax()) {
$articulos = DetalleArticulo::where('almacen_id', $request->almacen_id, 'articulo_id', $request->articulo_id)->firstOrFail();
return response()->json($articulos);
}
}
My item table is as follows:
<table class="table table-striped mt-0.5 table-bordered shadow-lg mt-4" id="articulo">
<thead class="bg-primary text-white">
<tr>
<th scope="col" width='60px'>Código</th>
<th scope="col">Imagen</th>
<th scope="col">Nombre</th>
<th scope="col">Categoría</th>
<th scope="col">Almacén</th>
<th scope="col">Disponible</th>
<th scope="col">Cantidad</th>
<th scope="col">Acciones</th>
</tr>
</thead>
<tbody>
@foreach ($articulos as $articulo)
<tr>
<td>{{ $articulo->codigo }}</td>
@if (isset($articulo->imagen))
<td class="text-center">
<img src="/imagen/{{$articulo->imagen}}" style="height: 50px; width: 50px; border-radius: 20%;">
</td>
@else
<td class="text-center"><img src="/imagen/caja.png"
alt="" width="70" height="70"></td>
@endif
<td>{{ Str::ucfirst($articulo->nombre) }}
</td>
<td>{{ Str::ucfirst($articulo->categoria->nombre) }}</td>
<td>
<select class="form-control selectpicker articuloB js-almacen-id" data-live-search="true" name="almacen_id" id="almacen_id" lang="es" index={{$articulo->id}}>
<option value="" data-icon="fas fa-box" disabled selected>Buscar almacén</option>
@foreach ($detallearticulos as $detallearticulo)
@if ($detallearticulo->articulo_id == $articulo->id)
<option value="{{ $detallearticulo->almacen_id }}">{{ $detallearticulo->almacen_id }} - {{ $detallearticulo->almacen->nom_alm }}</option>
@endif
@endforeach
</select>
</td>
<td style="width: 50px;">
<input type="text" name="stock" id="stock" class="form-control js-stock" disabled>
</td>
<td>
<input type="number" class="form-control js-cantidad" min="0" max="100" name="cantidad" step="1"
oninput="validity.valid||(value='')">
@if ($errors->has('cantidad'))
<div class="alert alert-danger">
<span class="error text-danger">{{ $errors->first('cantidad') }}</span>
</div>
@endif
</td>
<td class="text-right">
<input type="hidden" class="form-control js-articulo-id" name="articulo_id" value="{{$articulo->id}}">
<input type="hidden" class="form-control js-articulo-nombre" name="articulo_nombre" value="{{$articulo->nombre}}">
<div class="form-group">
<button type="button" class="btn btn-info float-right mt-1 js-agregar"><i class="fas fa-check"></i>Agregar</button>
</div>
</td>
</tr>
@endforeach
</tbody>
</table>
the problem in your code is that you are using an id to retrieve your selects with jquery and assign them a "change" event, this means that your event is only applied to the first element found with this id, since ids are used in HTML for single elements and jQuery also interprets it this way, instead of this you should use classes instead of ids if it is an element that is constantly repeated in your HTML document, so your select should be like this.
And when you retrieve and assign an event to your selects, you must retrieve the class of your select so that this event is applied to all the selects that you have with that class, while the value that the user selected is ideal for you to retrieve with the Event object delivered as a parameter to the function that executes your event, this would be as follows.
Now you have the same problem when modifying the values #stock, #articulo_id and #almacen_id, the latter redundant so I would omit it. By using ids for these html elements you are only modifying the value of the first element found in your HTML document, so these elements must also be assigned a class instead of an id. To retrieve them and modify their value, I suggest you give your select an attribute in which you specify which row of your table it corresponds to, in this way you can retrieve this attribute in your change event and modify the necessary values of that same row.
For this your select must contain the "index" attribute as follows.
And your change event would look like this:
I leave you an example where the aforementioned is applied in a more rudimentary way.
Greetings, I enclose links with suggested reading to better understand what was said above.
https://api.jquery.com/class-selector/
https://api.jquery.com/id-selector/
https://api.jquery.com/change/
https://api.jquery.com/eq/
https://api.jquery.com/attr/
UPDATE
Your code is not retrieving the information for the item you are modifying because you are not sending this parameter to your controller. For this you can specify the id of your article in an attribute of your select so it would be as follows:
Here I recommend that you use the $loop->index variable to assign the index attribute to your select, this value is available in the @foreach Loop in your blade templates.
Then in your change event of your select, you must add the id of your article to your HTTP request to your PHP controller, so it should look like this.
And then in your get_products_by_id function in your controller your where function is wrong, in your case you want to retrieve your ItemDetail when the store_id is the one received in your function AND the item_id is the one received in your function.
So this would correspond in SQL to a WHERE (condition1) AND (condition2) clause.
To replicate this clause using Eloquent in Laravel, one of the options is to pass an array to your where function, as follows.
Or you can also do it by separating your conditions into 2 where functions like this:
With this your code should work as you wish, I recommend that when it works you look for other ways to do the same using less code, in this way you will improve your logic when writing your code and you will become more familiar with the resources used.
I enclose other recommended reading links related to the resources used.
https://laravel.com/docs/9.x/blade#loops
https://laravel.com/docs/9.x/queries#where-clauses
Greetings, I hope I have helped you.