Error in updating field with dynamically generated row - javascript

I have inventory form to submit inventories to database. I'm facing an issue in updating unit cost and total cost of dynamically generated rows. As you can see in snapshots below. The name of products are fetching via autocomplete jQuery.
HTML CODE
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>#</th>
<th>Product Name/Code</th>
<th>Quantity</th>
<th>Unit Cost</th>
<th>Total Cost</th>
<th>Actions</th>
</tr>
</thead>
<tbody id="p_scents">
<tr>
<td>1</td>
<td><input id="product_id" type="text" name="product_id[]" hidden><input id="product_code" type="text" name="product_code[]" hidden><input class="product_name form-control" id="product_name" type="text" placeholder="Type product name/code here" name="products[]" required></td>
<td><input class="quantity form-control" id="quantity" type="text" placeholder="Quantity to Buy" name="quantity[]" required /></td>
<td><div class="input-group"><span class="input-group-addon">$</span><input class="cost form-control" id="cost" placeholder="Unit Cost" type="text" readonly /></div></td>
<td><div class="input-group"><span class="input-group-addon">$</span><input class="total form-control" id="total" placeholder="Total" type="text" readonly /></div></td>
<td><button class="btn btn-default" type="button" id="addScnt"><i class="fa fa-plus "></i> Item</button></td>
</tr>
</tbody>
</table>
jQuery CODE
<script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script type='text/javascript'>
jQuery(document).ready(function(){
var scntDiv = $('#p_scents');
var i = $('#p_scents tr').size() + 1;
$('#addScnt').click(function() {
scntDiv.append('<tr>'+
'<td>'+i+'</td>'+
'<td><input id="product_id" type="text" name="product_id[]" hidden><input id="product_code" type="text" name="product_code[]" hidden><input class="product_name form-control" id="product_name" type="text" placeholder="Type product name/code here" name="products[]" required></td>'+
'<td><input class="quantity form-control" id="quantity" type="text" placeholder="Quantity to Buy" name="quantity[]" required /></td>'+
'<td><div class="input-group"><span class="input-group-addon">$</span><input class="cost form-control" id="cost" placeholder="Unit Cost" type="text" readonly /></div></td>'+
'<td><div class="input-group"><span class="input-group-addon">$</span><input class="total form-control" id="total" placeholder="Total" type="text" readonly /></div></td>'+
'<td><a id="remScnt" class="btn btn-danger btn-xs"><span title="Delete" class="glyphicon glyphicon-remove"></span></a></td>'+
'</tr>');
i++;
//return false;
$('.product_name').autocomplete({
source:'http://localhost/Multi-Channel_Shipping/inc/auto_product.php',
minLength:2,
select:function(evt, ui)
{
// when a product is selected, populate related fields in this form
this.form.cost.value = ui.item.cost;
this.form.product_id.value = ui.item.product_id;
this.form.product_code.value = ui.item.product_code;
}
});
$('.quantity').keyup(function() {
updateTotal();
});
$('.cost').keyup(function() {
updateTotal();
});
var updateTotal = function () {
var input1 = parseFloat($('.quantity').val());
var input2 = parseFloat($('.cost').val());
if (isNaN(input1) || isNaN(input2)) {
if(!input2){
$('.total').val($('.quantity').val());
}
if(!input1){
$('.total').val($('.cost').val());
}
} else {
$('.total').val(input1 * input2);
}
};
var output_total = $('.total');
var total = input1 + input2;
output_total.val(total);
});
//Remove button
$(document).on('click', '#remScnt', function() {
if (i > 2) {
$(this).closest('tr').remove();
i--;
}
return false;
});
$('.product_name').autocomplete({
source:'http://localhost/Multi-Channel_Shipping/inc/auto_product.php',
minLength:2,
select:function(evt, ui)
{
// when a zipcode is selected, populate related fields in this form
this.form.cost.value = ui.item.cost;
this.form.product_id.value = ui.item.product_id;
this.form.product_code.value = ui.item.product_code;
}
});
$('.quantity').keyup(function() {
updateTotal();
});
$('.cost').keyup(function() {
updateTotal();
});
var updateTotal = function () {
var input1 = parseFloat($('.quantity').val());
var input2 = parseFloat($('.cost').val());
if (isNaN(input1) || isNaN(input2)) {
if(!input2){
$('.total').val($('.quantity').val());
}
if(!input1){
$('.total').val($('.cost').val());
}
} else {
$('.total').val(input1 * input2);
}
};
var output_total = $('.total');
var total = input1 + input2;
output_total.val(total);
});
</script>
AUTO_PRODUCT.PHP CODE
<?php
class DB
{
const DATABASE = 'multi-channel_shipping';
const HOST = 'localhost';
const USERNAME = 'root';
const PASSWORD = '';
static private $pdo;
static public function singleton()
{
if (!is_object(self::$pdo))
{
self::$pdo = new PDO('mysql:dbname=' . self::DATABASE . ';host=' . self::HOST,
self::USERNAME,
self::PASSWORD);
}
return self::$pdo;
}
private function __construct()
{
}
public function __clone()
{
throw new Exception('You may not clone the DB instance');
}
}
if (!isset($_REQUEST['term']))
{
die('([])');
}
$st = DB::singleton()
->prepare(
'SELECT * ' .
'FROM products ' .
'WHERE (name LIKE :name) OR (code LIKE :name) ' .
'ORDER BY name ASC ' .
'LIMIT 0,10');
$searchProduct = '%'.$_REQUEST['term'].'%';
$st->bindParam(':name', $searchProduct, PDO::PARAM_STR);
$data = array();
if ($st->execute())
{
while ($row = $st->fetch(PDO::FETCH_OBJ))
{
$data[] = array(
'value' => $row->code." - ".$row->name,
'cost' => $row->cost,
'product_id' => $row->id,
'product_code' => $row->code
);
}
}
echo json_encode($data);
flush();
?>
MySQL Data
--
-- Table structure for table `products`
--
CREATE TABLE IF NOT EXISTS `products` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`code` varchar(100) NOT NULL,
`name` varchar(255) NOT NULL,
`unit` varchar(50) DEFAULT NULL,
`cost` decimal(25,2) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `code` (`code`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ;
--
-- Dumping data for table `products`
--
INSERT INTO `products` (`id`, `code`, `name`, `unit`, `cost`) VALUES
(1, '4815162342', 'BAZIC 12 Dil Dil Pak', 'Packet', '0.10'),
(2, '23', 'Razer', 'Piece', '0.03');
I also need to put shipping cost input field and show grand total of invoice at bottom of table.

There a multiple issues with the page & code, so I will try to cover what I can. #Barmar also spotted additional issues so will try to cover everything and suggest some improvements.
JSFiddle: http://jsfiddle.net/TrueBlueAussie/vx15mr4n/29/
Templating:
Rather than use text strings in code, it is easier to maintain HTML as HTML. The example I have provided uses a dummy script block (of type="text/template", which will be ignored by all browsers) but you can access the HTML content with $('#template').html().
Duplicate ID are invalid
You can't have duplicate IDs in a page. That is invalid HTML and jQuery will only see the first match. Use classes on the added elements instead and match on those.
so use:
<a class="remScnt"
and
$(document).on('click', '.remScnt', function()
Note: you will need to sort out any other duplicate IDs too (like product_id and quantity and cost and total). Your code already uses classes for those, so just move/delete the id attributes.
e.g. use classes for everything:
scntDiv.append('<tr>'+
'<td>'+i+'</td>'+
'<td><input class="product_id" type="text" name="product_id[]" hidden><input id="product_code" type="text" name="product_code[]" hidden><input class="product_name form-control" type="text" placeholder="Type product name/code here" name="products[]" required></td>'+
'<td><input class="quantity form-control" type="text" placeholder="Quantity to Buy" name="quantity[]" required /></td>'+
'<td><div class="input-group"><span class="input-group-addon">$</span><input class="cost form-control" placeholder="Unit Cost" type="text" readonly /></div></td>'+
'<td><div class="input-group"><span class="input-group-addon">$</span><input class="total form-control" placeholder="Total" type="text" readonly /></div></td>'+
'<td><a class="remScnt btn btn-danger btn-xs"><span title="Delete" class="glyphicon glyphicon-remove"></span></a></td>'+
'</tr>');
You are using a delegated event for one handler but not the others. You also need to add them for keyup (which can be combined as the code is the same):
$('#p_scents').on('keyup', '.quantity .cost', function() {
updateTotal();
});
IMPORTANT: Your code here is not matching a specific row. Also use #Barmar's fix like this to pass the current row:
$('#p_scents').on('keyup', '.quantity .cost', function() {
updateTotal($(this).closest('tr'));
});
Update: As Regent mentions below, you should not use document but use #p_scents for your delegated event handler:
$('#p_scents').on('click', '.remScnt', function()
A delegated event should be attached to the closest non-changing ancestor (if one is convenient/available). This will give a very small speed increase as it stops lower in the DOM.
I also cleaned up the event handler doing the calculations which now using temp vars, for elements relative to the row, and looks like:
// Update the row total of a specific row
var updateTotal = function ($row) {
// Get the specific inputs
var $quantity = $('.quantity', $row);
var $cost = $('.cost', $row);
var $total = $('.total', $row);
var input1 = parseFloat($quantity.val());
var input2 = parseFloat($cost.val());
if (isNaN(input1) || isNaN(input2)) {
if (!input2) {
$total.val($quantity.val());
}
if (!input1) {
$total.val($cost.val());
}
} else {
$total.val(input1 * input2);
}
var total = input1 * input2;
$total.val(total);
};
Note: Without the missing data, I cannot easily test the code, but you should get the idea.
Grand total
To update the grand total, you need to iterate all .total fields and add them to the shipping cost:
var updateGrandTotal = function()
{
// Now update the grand total
var grandTotal = 0;
$('.total').each(function () {
grandTotal += parseFloat($(this).val());
});
var shipping = parseFloat($('.shippingcost').val());
$('.grandtotal').val(grandTotal + shipping);
}
As you will want to update the grand total when the shipping changes, I refactored it out so it could also be called from a keyup on the shipping:
$('.shippingcost').keyup(function(){
updateGrandTotal();
});
The other issue is the autocomplete (which I could not test without a real data feed):
Basically get the select event to refer to the current field's row and find the appropriate fields to update:
JSFiddle: http://jsfiddle.net/TrueBlueAussie/vx15mr4n/23/
select: function (evt, ui) {
// when a product is selected, populate related fields in this form
var $tr = $(this).closest("tr");
$(".cost",$tr).val(ui.item.cost);
$(".product_id", $tr).val(ui.item.product_id);
$(".product_code", $tr).val(ui.item.product_code);
}

When updateTotal() uses $('.quantity').val() it gets the value of the first field with that class, not the one in the row that the user was typing in. You need to pass the row to the function. Also, since the elements are added dynamically, you need to use delegation for the event bindings.
$('#p_scents').on('keyup', '.quantity, .cost', function() {
updateTotal($(this).closest('tr'));
});
var updateTotal = function (row) {
var input1 = parseFloat($('.quantity', row).val());
var input2 = parseFloat($('.cost', row).val());
if (isNaN(input1) || isNaN(input2)) {
if(!input2){
$('.total', row).val(input1);
}
if(!input1){
$('.total', row).val($(input2);
}
} else {
$('.total', row).val(input1 * input2);
}
}
var output_total = $('.total', row);
var total = input1 + input2;
output_total.val(total);
};

Related

How to create a function for Onkeyup

I am trying to write a function to analyze the users input before calling Onkeyup. I am not sure where to write this if statement, or if I have the correct syntax. I wrote the if statement inside the asset-tag class. This is my code:
const getAssetInfo = (assetTag, index) => {
// get the table row that this input is in
$.get("http://localhost:3000/assets/" + assetTag , (data) => {
// find the `.description` element and set it's value
if (data){
$(`#manufacturer_serial_no${index}`).val(data.serial_no);
$(`#description${index}`).val(data.description);
$(`#cost${index}`).val(data.cost);
$(`#po_no${index}`).val(data.po_no);
}
console.log(data);
})
.fail(() => {
// alert("DONE");
// console.log(index);
$(`#manufacturer_serial_no${index}`).val("");
$(`#description${index}`).val("");
$(`#cost${index}`).val("");
$(`#po_no${index}`).val("");
});
};
$('document').ready(() => {
// Handler to Add New Asset
const table = $("#formTable tbody");
let count = 1;
$('#add').click(() => {
const newRow = `
<tr index="${count}">
<form>
<td><input
class="asset-tag" id='asset_tag_no${count}' type='text'
if (input.length >= 4){
console.log('not enough characters to call API endpoint');
}
else{
onkeyup = "getAssetInfo(this.value,${count})";
}
bottom required /></td>
<td><input class="serial-no" id='manufacturer_serial_no${count}' type='text' bottom required readonly/></td>
<td><textarea class="description" id='description${count}' type='text' bottom required readonly description></textarea></td>
<td><input id='cost${count}' type='value' bottom require readonly/></td>
<td><input id='po_no${count}' type='text' bottom require readonly/></td>
<td><textarea id='remarks${count}' type='text' bottom remarks></textarea></td>
<td><button type="button" index="${count}" class="btn btn-danger btn-remove">X</button></td>
</form>
</tr>
`;
table.append(newRow);
// Handler to Remove New Asset
$('.btn-remove').click(function(){
let index = $(this).attr('index');
$(`tr[index='${index}'`).remove();
});
count++;
});
I want this error in the console log to only execute when a certain amount of characters are in the box instead of each time a character is inputted.

How to submit the dynamical input field into the database?

I am displaying the input field dynamically which is working for me.
The issue is,
I have to submit the form. I have tried some code as below but it's not working.
I am using Codeigniter.
Controler code
public function register(){
$save = array(
'pp_fileStatus' => $this->input->post('pp_fileStatus');
'reasonDate' => $this->input->post('reasonDate');
'reasonAmt' => $this->input->post('reasonAmt');
);
$afterxss=$this->security->xss_clean($save);
if ($afterxss)
{
$this->db->insert('tbl_register',$afterxss);
$response['error'] = "true";
$response['msg'] = "Successfully";
}else{
$response['error'] = "false";
$response['msg'] = "Sometning wrong! please check the internet connection and try again";
}
echo json_encode($response);
}
I am adding the field dynamically and incrementing the name. Please let me know what name I have to use here
$save = array(
'pp_fileStatus' => $this->input->post('pp_fileStatus');
'reasonDate' => $this->input->post('reasonDate');
'reasonAmt' => $this->input->post('reasonAmt');
);
Below is the code for adding the input field dynamically.
$(document).ready(function() {
var maxField = 10; //Input fields increment limitation
var x = 1; //Initial field counter is 1
var count = 2;
var numberIncr = 1; // used to increment the name for the inputs
var addrm = '';
//Once add button is clicked
$(document).on('click', '#clicktoadd', function() {
//Check maximum number of input fields
if (x < maxField) {
x++; //Increment field counter
numberIncr++;
$(".medication_info").append('<select name="pp_fileStatus' + numberIncr + '" class="form-control multipleselect pp_fileStatus dynamicVal"><option value="" disabled selected>Status</option><option value="1">Open</option><option value="2">Close</option><option value="3">Pending</option></select>');
}
count++;
});
$(document).on('change', '.pp_fileStatus', function(event) {
if (($(this).val() == '1') || ($(this).val() == '3')) {
$(".medication_info").append('<div class="addbankField input-wrapper padding0"><div class="form-group"> <input type="text" name="reasonDate' + numberIncr + '" class="form-control datetimepicker dynamicVal" placeholder="Date"></div></div><div class="addbankField input-wrapper"><div class="form-group"> <input type="text" name="reasonAmt' + numberIncr + '" class="form-control commnumber dynamicVal" placeholder="amt"></div></div><input type="hidden" name="remark' + numberIncr + '" class="form-control" placeholder="Remark">');
} else {
$(".medication_info").append('<div class="addbankField input-wrapper lbpflex padding0"><div class="form-group"> <input type="text" name="reasonDate' + numberIncr + '" class="form-control datetimepicker dynamicVal" placeholder="Date"></div></div><div class="addbankField input-wrapper"><div class="form-group"> <input type="text" name="remark' + numberIncr + '" class="form-control dynamicVal" placeholder="Remark"></div></div><input type="hidden" name="reasonAmt' + numberIncr + '" class="form-control" placeholder="amt">');
}
});
});
$('#register').on('submit', function(event) {
event.preventDefault();
// adding rules for inputs with class 'comment'
$('.dynamicVal').each(function() {
$(this).rules("add", {
required: true
})
});
// test if form is valid
if ($('#register').validate().form()) {
$.ajax({
//url:"process.php",
url: baseUrl + "/Customer_control/register",
type: "POST",
dataType: "json",
data: $('#register').serialize(),
success: function(data) {
alert("success");
},
}); // AJAX Get Jquery statment
}
//alert('hellow');
});
$('#register').validate({
errorPlacement: function(error, element) {
if (element.is("select")) {
error.insertAfter(element.parent());
} else {
error.insertAfter(element);
}
}
});
<div id="clicktoadd">Add More</div>
<form action="#" method="post" id="register" name="register">
<div class="row">
<div class="medication_info">
</div>
</div>
<input type="submit" name="send" value="submit">
</form>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.1/jquery.validate.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.1/additional-methods.min.js"></script>
Can anyone here to help me out with this issue?
You can use arrays for multiple names in HTML form and then get the values using Foreach Loop in PHP (CodeIgniter).
Here is how you should change your code: Change your this line:
$(".medication_info").append('<select name="pp_fileStatus' + numberIncr + '" class="form-control multipleselect pp_fileStatus dynamicVal"><option value="" disabled selected>Status</option><option value="1">Open</option><option value="2">Close</option><option value="3">Pending</option></select>')
To:
$(".medication_info").append('<select name="pp_fileStatus[]" class="form-control multipleselect pp_fileStatus dynamicVal"><option value="" disabled selected>Status</option><option value="1">Open</option><option value="2">Close</option><option value="3">Pending</option></select>')
Note: I just changed select field name to "pp_fileStatus[]" and remove numberIncr variable
Now you can access this field name values in your controller like this.
$pp_fileStatus = $this->input->post('pp_fileStatus');
Here $pp_fileStatus is an array and contains all the values of pp_fileStatus.
You can do same for your other form fields too.
So you get rid of giving names to fields by incrementing one to a variable.
Hope this solves your problem.
You can update your register function like this:
public function register(){
$insert_array = [];
$pp_fileStatus = $this->input->post('pp_fileStatus');
$reasonDate = $this->input->post('reasonDate');
$reasonAmt = $this->input->post('reasonAmt');
$remark = $this->input->post('remark');
foreach ($pp_fileStatus as $key => $value) {
$insert_array[] = array(
'pp_fileStatus' => $value,
'reasonDate' => $reasonDate[$key],
'reasonAmt' => $reasonAmt[$key],
'remark' => $remark[$key]
);
}
$this->db->insert_batch('tbl_register',$insert_array);
}
Update this function according to your needs
you need to create a function for your submit actions, which you call (make available) on document load and also with your change event, after having appended the DOM.
simplified example:
$(document).ready(function() {
my_submit(); // enables your submit calls
$(document).on('change', '.pp_fileStatus', function(event) {
// your append code
my_submit(); // again, enables your submit calls
})
}
function my_submit(){
$('#register').on('submit', function(event) {
// your code
})
$('#register').validate({
// your code
})
}

jquery: how to update input value using onchange?

I created a discount function for my order page where I have an issue that is , on my order page by default when product quantity is 1 then discounted rate show correctly in Final textbox but when I change the Quantity, like 1 to 2,3,4,5.. then my code not works and the amount show without discount rate.
I try to fix this but I not understand where is mistake and how I fix that.
Below is my code which I am using please help and tell me how I make this correct.
Your help will be really appreciate.
Thank you!
function getTotal(row = null) {
if(row) {
var disc = $('#dis_1').val();//
var dec = (disc/100).toFixed(2); //
var total = Number($("#rate_value_"+row).val()) * Number($("#qty_"+row).val()) * dec;
//total = total.toFixed(2);
var rate = Number($("#rate_value_"+row))-total;
total = total.toFixed(2);
$("#amount_"+row).val(total);
$("#amount_value_"+row).val(total);
subAmount();
} else {
alert('no row !! please refresh the page');
}
}
//**---**/
//*---*//
// get the product information from the server
function getProductData(row_id)
{
var product_id = $("#product_"+row_id).val();
if(product_id == "") {
$("#rate_"+row_id).val("");
$("#rate_value_"+row_id).val("");
$("#qty_"+row_id).val("");
$("#amount_"+row_id).val("");
$("#amount_value_"+row_id).val("");
} else {
$.ajax({
url: base_url + 'orders/getProductValueById',
type: 'post',
data: {product_id : product_id},
dataType: 'json',
success:function(response) {
// setting the rate value into the rate input field
$("#rate_"+row_id).val(response.price);
$("#rate_value_"+row_id).val(response.price);
$("#dis_"+row_id).val(response.discount);
$("#dis_value_"+row_id).val(response.discount);
$("#qty_"+row_id).val(1);
$("#qty_value_"+row_id).val(1);
//DISCOUNT
var disc = $('#dis_1').val();
var dec = (disc/100).toFixed(2);
var total = Number(response.price) * dec;
var rate = Number(response.price)-total;
total = rate.toFixed(2);
$("#amount_"+row_id).val(total);
$("#amount_value_"+row_id).val(total);
subAmount();
} // /success
}); // /ajax function to fetch the product data
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<td><input type="text" name="qty[]" id="qty_1" class="form-control" required onkeyup="getTotal(1)" placeholder="Quantity"></td>
<td>
<input type="text" name="rate[]" id="rate_1" class="form-control" autocomplete="off" placeholder="Rate">
</td>
<td>
<input type="text" placeholder="Discount" name="dis[]" id="dis_1" class="form-control" autocomplete="off">
</td>
<td>
<input type="text" placeholder="Total Price" name="amount[]" id="amount_1" class="form-control" autocomplete="off">
</td>
I am using my database to fetch the amount like product real rate, discounts.
In your line of HTML
<td><input type="text" name="qty[]" id="qty_1" class="form-control" required onkeyup="getTotal(1)" placeholder="Quantity"></td>
you are always calling getTotal with a value of 1, I think you want to instead get the value of the text box when the getTotal function is called and use that as your row value. In jquery you can get the value of the box by
row = $("#qty").val()

How to calculate each table row indipendently on keyup

<tbody id="dailysale_tbody">
<tr class="items">
<td><select id="items_select" name="dailysale[luitem_id]"><option value=""></option></select></td>
<td><select id="brands_select" name="dailysale[lubrand_id]"><option value=""></option></select></td>
<td><select id="models_select" name="dailysale[lumodel_id]"><option value=""></option></select></td>
<td><input class="texts" id="dailysale_qty" name="dailysale[qty]" type="text" /></td>
<td><input class="texts" id="dailysale_price" name="dailysale[price]" type="text" /></td>
<td><input class="texts" id="dailysale_total" name="dailysale[total]" type="text" /></td>
<td><input type="checkbox" class="delete_row"></td>
</tr>
$(function() {
$('#dailysale_qty, #dailysale_price').keyup(function() {
var last_item = $('.items').find('#dailysale_qty');
var qty = last_row.find('#dailysale_qty').val();
var price = last_row.find('#dailysale_price').val();
var sub_total = last_row.find('#dailysale_total');
var s_total = qty * price;
if (isNaN(s_total)) {
sub_total.val('0');
}
else
sub_total.val(s_total);
});
});
I am able to perform calculations on this row. However, when I dynamically add rows with jquery, calculations are not working on the other rows.
When the calculating function is bind a button onclick, everything works well. But not on input keyup as required. I want to perform calculations on the new added row with onkeyup on qty and price input fields.
Note than upon cloning, the ids are stripped of the current row and assigned to the new row for reference.
You probably not registering keyup function when you adding new row.
You should do :
$('#dailysale_qty, #dailysale_price').unbind('keyup').keyup( function(...
Every time you adding new row.
#Nosyara The suggested line of code isn't working. Here is how am adding new rows. The commented line is what you suggested.
$(function(){
$('#newitembtn').click(function(){
//$('#dailysale_qty, #dailysale_price').unbind('keyup').keyup(function() {
var last_row = $('#dailysale_tbody').find('tr:last');
var newrow = last_row.clone();
last_row.find('#items_select').removeAttr('id');
last_row.find('#brands_select').removeAttr('id');
last_row.find('#models_select').removeAttr('id');
last_row.find('#dailysale_qty').removeAttr('id');
last_row.find('#dailysale_price').removeAttr('id');
last_row.find('#dailysale_total').removeAttr('id');
newrow.find('#items_select').val('');
newrow.find('#brands_select').val('');
newrow.find('#models_select').val('');
newrow.find('#dailysale_qty').val('');
newrow.find('#dailysale_price').val('');
newrow.find('#dailysale_total').val('');
last_row.after(newrow);
});
});
});

handle incrementing number of array ID in duplicated form field set (regex)

I need to duplicate rows of a form ( in a table )
See jsbin here : http://jsbin.com/ExiRAMa/1/edit
The markup :
<div id="o99_the_work">
<table><tbody>
<tr>
<!-- THE ORDER -->
<td>X</td>
<td class="small-text"><span class="wpcf7-form-control-wrap submitted-file"><input type="file" name="submitted-file" value="1" size="40" class="wpcf7-form-control wpcf7-file" id="submitted-file-1"></span></td>
<td><span class="wpcf7-form-control-wrap number-of-copies"><input type="text" name="number-of-copies" value="" size="40" class="wpcf7-form-control wpcf7-text small-text" id="number-of-copies-1"></span></td>
<td><span class="wpcf7-form-control-wrap checkbox-copy-type"><span class="wpcf7-form-control wpcf7-checkbox" id="copy-type-1"><span class="wpcf7-list-item"><input type="checkbox" name="checkbox-copy-type[]" value="color"> <span class="wpcf7-list-item-label">color</span></span><span class="wpcf7-list-item"><input type="checkbox" name="checkbox-copy-type[]" value="bw"> <span class="wpcf7-list-item-label">bw</span></span><span class="wpcf7-list-item"><input type="checkbox" name="checkbox-copy-type[]" value="transperant"> <span class="wpcf7-list-item-label">transperant</span></span><span class="wpcf7-list-item"><input type="checkbox" name="checkbox-copy-type[]" value="pergament"> <span class="wpcf7-list-item-label">pergament</span></span></span></span></td>
<td><span class="wpcf7-form-control-wrap submitted-remarks"><input type="text" name="submitted-remarks" value="" size="40" class="wpcf7-form-control wpcf7-text" id="submitted-remarks-1"></span> </td>
</tr></tbody></table>
<button id="add_row">Add new</button>
</div>
The JS :
jQuery("#add_row").click(function() {
var row = jQuery("#k99_the_work tbody > tr:last"),
newRow = row.clone(true);
newRow.find("input[type=text],input[type=file]").each(function() {
var num = +(this.id.match(/\d+$/) || [0])[0] + 1;
this.id = this.id.replace(/\d+$/, "") + num;
this.name = this.id;
});
newRow.insertAfter(row);
return false;
});
As you can see from the bin, the scripts works fine on input=text and it is incrementing both the name and ID - but my problem is how to deal with the checkboxes .
I need to increment the name, ID etc , while keeping it seperate arrays checkbox-copy-type[] .
Meaning , after duplication i need checkbox-copy-type-1[], checkbox-copy-type-2[] etc
I am by no means a regex person, but I tried adding :
newRow.find("input[type=checkbox]").each(function() {
var num = +(this.id.match(/checkbox-copy-type/) || [0])[0] + 1;
// this.id = this.name.replace(/\[]/, "vv") + num;
this.id = this.name.replace(/\[]/, "") + num;// take off the brackets
this.id = this.name + "[]" ;// add the brackets again
this.name = this.id;
});
But all I get when I try this is another set of brackets e.g. checkbox-copy-type[][] ,checkbox-copy-type[][][]
You can store the item in the data portion of html (if its unique for each tr/checkbox) retrieve it that way and then increment it, then add the brackets in.
HTML
<tr data-name="myName"></tr>
javascript
newRow.find("input[type=checkbox]").each(function(x, item) {
var name = $(item).data('name'); //this give you the name if it unique
var newName = name + x + '[]' // this give final result
});
I have resolved it like so :
newRow.find("input[type=checkbox]").each(function() {
var parentid = jQuery(this).parent().parent();
var num = +(this.id.match(/checkbox-copy-type+$/) || [0])[0] + 1;
this.id = this.name.replace(/\d+/, function(val) { return parseInt(val)+1; });
this.name = this.id;
parentid.attr("id",parentid.attr("id").replace(/\d+/, function(val) { return parseInt(val)+1; }));
});

Categories

Resources