I am working on an inventory management system that involves sales of products
The form is dynamic
when a user click on add new product it sends to the server and get the price of the product
My HTML Code
<form role="form" action="{{ url('admin/sales/store') }}" method="get">
@csrf
<div >
<div >
<div >
</div>
<div >
<a href="#" id="add-product">Add New Product</a>
</div>
<div id="wrapper" >
<div id="new-field" >
<div >
<div >
<div >
<label>Product Name</label>
<select name="product[]" id="product" >
<option value="">Select Product Name</option>
@foreach ($products as $product)
<option value="{{ $product->id }}" name="product[]">
{{ $product->name }}</option>
@endforeach
</select>
</div>
</div>
<div >
<div >
<label>Quantity</label>
<input type="text" name="quantity[]"
value="{{ old('quantity') }}"
placeholder="Enter Quantity">
</div>
</div>
<div >
<div >
<label>Unit Price</label>
<input type="text" name="price[]" disabled
id="price"
placeholder="Enter Quantity">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div >
<button type="submit" >Add Sales</button>
</div>
</form>
JQUERY
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
$("#add-product").click(function(e) {
e.preventDefault();
$("#new-field").clone().appendTo("#wrapper");
});
$("#product").change(function(e) {
e.preventDefault();
axios.get("/ims/api/get-price/" $(this).val())
.then(function(response) {
$("#price").val(response.data.price);
});
})
</script>
JSON
{
price: 34000.42
}
but it is only the first row that works
How can I make other rows to work?
CodePudding user response:
The issue is that you're using the id
attribute to select your elements.
Initially, your product rows (simplified) look like this:
<div id="wrapper">
<div id="new-field">
...
<select name="product[]" id="product"></select>
...
<input type="text" name="quantity[]" value="{{ old('quantity') }}" >
...
<input type="text" name="price[]" disabled id="price">
...
</div>
</div>
After the #add-product
element is clicked, you clone the whole #new-field
element, and append it to the #wrapper
element with this code:
$("#add-product").click(function(e) {
e.preventDefault();
$("#new-field").clone().appendTo("#wrapper");
});
Then the simplified view of your product rows looks like this:
<div id="wrapper">
<div id="new-field">
...
<select name="product[]" id="product"></select>
...
<input type="text" name="quantity[]" value="{{ old('quantity') }}" >
...
<input type="text" name="price[]" disabled id="price">
...
</div>
<div id="new-field">
...
<select name="product[]" id="product"></select>
...
<input type="text" name="quantity[]" value="{{ old('quantity') }}" >
...
<input type="text" name="price[]" disabled id="price">
...
</div>
</div>
Note particularly that you have doubled-up id
attributes for new-field
, product
and price
.
id
is supposed to be unique in HTML.
Then, when your price update code runs, it's always going to cause an issue. The HTML engine in your browser is ignoring all the duplicate id
attributes:
// This line tries to get the unique element with the id "product"
// after it's found it (i.e. the first element in the DOM), it stops
// so this line only selects the first element with an id of "product"
$("#product").change(function(e) {
e.preventDefault();
axios.get("/ims/api/get-price/" $(this).val())
.then(function(response) {
// This line tries to get the unique element with the id
// "price", after it finds the first one, it stops looking
// so this will never select the duplicated elements.
$("#price").val(response.data.price);
});
})
To fix it, you need to stop using id
to select the product. Do something like this:
Change your id attributes on the #new-field
, #product
and #price
elements to class:
<div >
<select name="product[]" ></select>
...
<input type="text" name="price[]" disabled >
</div>
And modify your JS to select based on class:
$(".wrapper").on('change', '.product', function(e) {
e.preventDefault();
axios.get("/ims/api/get-price/" $(this).val())
.then(function(response) {
$(this).parent('.new-field').find('.price').val(response.data.price);
});
})
You'll also need to update your JavaScript to correctly add new products.