How Do I Send Request To Server From A Dynamic Form Using Jquery
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 class="card-body">
<div class="row">
<div class="col-md-12">
</div>
<div class="col-md-12 right my-3">
<a href="#" class="btn btn-danger" id="add-product">Add New Product</a>
</div>
<div id="wrapper" class="col-md-12">
<div id="new-field" class="col-md-12">
<div class="row">
<div class="col-md-4">
<div class="form-group">
<label>Product Name</label>
<select name="product[]" id="product" class="form-control">
<option value="">Select Product Name</option>
@foreach ($products as $product)
<option value="{{ $product->id }}" name="product[]">
{{ $product->name }}</option>
@endforeach
</select>
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label>Quantity</label>
<input type="text" name="quantity[]" class="form-control"
value="{{ old('quantity') }}"
placeholder="Enter Quantity">
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label>Unit Price</label>
<input type="text" name="price[]" disabled
id="price"
class="form-control"
placeholder="Enter Quantity">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="card-footer">
<button type="submit" class="btn btn-primary float-md-right">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?
Answer
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 class="new-field">
<select name="product[]" class="product"></select>
...
<input type="text" name="price[]" disabled class="price">
</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.
Related Questions
- → OctoberCMS - How to make collapsible list default to active only on non-mobile
- → How to update data attribute on Ajax complete
- → October CMS - Radio Button Ajax Click Twice in a Row Causes Content to disappear
- → Octobercms Component Unique id (Twig & Javascript)
- → when i send data with ajax(jquery) i don't find the values in controller without form in laravel 5.1
- → DropzoneJS & Laravel - Output form validation errors
- → Knockout JS - How to return empty strings for observable fields
- → How to replace *( in a string
- → Get the calling element with vue.js
- → Sent Variable to Controller via Ajax in Blade
- → AJAX folder path issue
- → Onclick with argument causes javascript syntax error
- → KNockout JS - Automatic reload of ajax call