Reputation: 279
I am using CouchCMS. In CouchCMS there is a concept of repeatable regions. This in fact generates tables and displays the repeatable contents in it.
I have the repeatable region defined as:
<cms:repeatable name="item_detail" label="Item Detail" order="10" >
<cms:editable name="product" label="Product" type="dropdown" opt_values="Select =- | <cms:pages masterpage='product/product.php' order='asc' orderby='product_name'><cms:show product_name /><cms:if '<cms:not k_paginated_bottom />'>|</cms:if></cms:pages>" order="1" />
<cms:editable name="product_hsn" label="HSN" type="text" order="2" />hsn,qty,price,gst,amount
<cms:editable name="product_qty" label="Quantity" type="text" order="3" />
<cms:editable name="product_price" label="Price" type="text" order="4" />
<cms:editable name="product_tax" label="Tax" type="text" order="5" />
<cms:editable name="product_line_total_amount" label="Amount" type="text" order="6" />
</cms:repeatable>
Where the editables are the regions where we can fill in the data by bounding them to the respective textboxes/ selects, etc.
Now What I am trying to do is:
But what I really want to do is:
Now the repeatable region creates a structure as follows ( for the above defined repeatable region):
Product | HSN | Quantity | Price | Tax | Amount | Delete |
---|
<div>
<p class="addRow" id="addRow_f_item_detail"><a>Add a Row</a></p>
</div>
I can add new rows also right out of the box when using repeatable regions. If one observes ids and the names have a zero [0] this keeps on incrementing as one would add the new rows. The script helping in this above code generation is:
if ( !window.COUCH ) var COUCH = {};
$(function(){
$('table.rr > tbody').sortable({
axis: "y",
handle: ".dg-arrange-table-rows-drag-icon",
helper: function (e, ui) {
// https://paulund.co.uk/fixed-width-sortable-tables
ui.children().each(function() {
$(this).width($(this).width());
});
return ui;
},
update: function( event, ui ){
var row = ui.item;
var tbody = $( row ).closest( 'tbody' );
tbody.trigger('_reorder');
},
start: function( event, ui ){
var row = ui.item;
row.trigger('_reorder_start');
},
stop: function( event, ui ){
var row = ui.item;
row.trigger('_reorder_stop');
},
});
});
COUCH.rrInit = function( field_id, default_row ){
var $field = $('#'+field_id);
$field.tableGear({addDefaultRow:default_row, stackLayout:1});
$field.on('click', '.col-actions .add-row', function(){
var $this = $(this);
var row_id = $this.attr('data_mosaic_row');
var add_btn = $('#addRow_'+field_id+' a');
add_btn.trigger("click", [row_id]);
});
}
COUCH.t_confirm_delete_row = "Delete this row?";
COUCH.t_no_data_message = "- No Data -";
Just in case if required this is my AJAX code, using which I am able to add a new but it is in a New while I want the to be appended to the same that contains the existing repeatable regions. AJAX CODE:
$(document).on('change','select',function() {
var data = "";
$.ajax({
type:"GET",
url : "<cms:show k_site_link />generate/quotation-ajax.php",
data:
"select_id="+$(this).val(),
async: false
}).done(function(data) {
console.log(data);
var trHTML = '';
$.each(data.product_details, function (i, item) {
trHTML += "<tr id='f_item_detail-" + i + "'>" + '<td class="editable k_element_product_hsn"><div style="position:relative;"><input type="bound" name=" f_item_detail[0][product_hsn]" id="f_item_detail-[0]-product_hsn" class="form-control" value="' + item.product_hsn + '"/></div></td>' +
// '<td style="position:relative;"><input type="bound" name=" f_item_detail[0][product_price]" id="f_item_detail-[0]-product_price" class="form-control" value="' + item.product_price + '"/></td>' +
// '<td style="position:relative;"><input type="bound" name=" f_item_detail[0][product_tax]" id="f_item_detail-[0]-product_tax" class="form-control" value="' + item.product_tax + '"/></td>' +
'</tr>';
});
$('#f_item_detail').append(trHTML);
})
});
And my AJAX file has the code:
<?php require_once('../couch/cms.php'); ?>
<cms:set selected_product="<cms:gpc 'select_id' method='get' />" scope="global" />
<cms:content_type 'application/json'/>
<cms:template title="Quotation AJAX" hidden='1' parent="_generate_" />
{
"product_details":
[
<cms:pages masterpage='product/product.php' custom_field="product_name=<cms:show selected_product />" >
{
"product_hsn": "<cms:addslashes><cms:show product_hsn/></cms:addslashes>",
"product_price": "<cms:addslashes><cms:show min_selling_cost/></cms:addslashes>",
"product_tax": "<cms:addslashes><cms:show tax_on_purchase/></cms:addslashes>"
}<cms:if "<cms:not k_paginated_bottom/>">,</cms:if>
</cms:pages>
]
}
<?php COUCH::invoke(); ?>
What I am looking for: Add the AJAX success JSON values to the respective textboxes in the existing , and rather than adding a new or or . I am unable to set the correct jQuery. Any help would be really appreciated.
Thanks in advance. Regards! @Swati: Full HTML in this fiddle (with some changes in the AJAX part, which partially works and outputs what I want to achieve. The value is put into the textbox but for each new row the same textbox value is updated from the first row, if i could update the textbox values row wise it would be great)
EDIT #1 I have used your code (@Swati) as follows and yes it works fine (to an extent).
<script type="text/javascript">
$(document).ready(function(){
$("#f_item_detail-0-product").select2();
$('input#f_item_detail-0-product_hsn').attr('readonly', true).addClass("form-control");
$('input#f_item_detail-0-product_qty').attr('onchange', 'line_total()');
$('input#f_item_detail-0-product_price').attr('onchange', 'line_total()');
$('input#f_item_detail-0-product_tax').attr('readonly', true).addClass("form-control");
$('input#f_item_detail-0-line_tax_amount').attr('readonly', true).addClass("form-control");
$('input#f_item_detail-0-product_line_total_amount').attr('readonly', true).addClass("form-control");
});
var counter = 0;
$(document).ready(function() {
$(".addRow").click(function(){
counter++;
$("#f_item_detail-" + counter + "-product").select2();
});
});
$(document).on('change','select',function() {
var data = "";
var i = 0;
var indexs = $(this).closest("tr").index();//get index no
console.log(indexs);
$.ajax({
type:"GET",
url : "<cms:show k_site_link />generate/quotation-ajax.php",
data:
"select_id="+$(this).val(),
async: false
}).done(function(data) {
$('#f_item_detail-' + indexs + '-product_hsn').val(data.product_details[i].product_hsn).attr('readonly', true).addClass("form-control");
$('#f_item_detail-' + indexs + '-product_qty').attr('onchange', 'line_total()');
$('#f_item_detail-' + indexs + '-product_price').val(data.product_details[i].product_price).attr('onchange', 'line_total()');
$('input#f_item_detail-' + indexs + '-product_tax').val(data.product_details[i].product_tax).attr('readonly', true).addClass("form-control");
$('#f_item_detail-' + indexs + '-line_tax_amount').attr('readonly', true).addClass("form-control");
$('#f_item_detail-' + indexs + '-product_line_total_amount').val(data.product_details[i].product_line_total_amount).attr('readonly', true).addClass("form-control");
});
});
function line_total(){
var line_qty = $('input#f_item_detail-' + indexs + '-product_qty').val();
var line_tax = $('input#f_item_detail-' + indexs + '-product_tax').val();
var line_cost = $('input#f_item_detail-' + indexs + '-product_price').val();
var line_tax_amount = parseFloat(((line_cost * line_tax)/100) * line_qty).toFixed(2);
var result = parseFloat((+line_qty * +line_cost) + +line_tax_amount).toFixed(2);
$('#f_item_detail-' + indexs + '-line_tax_amount').val(line_tax_amount).attr('hidden',true);
$('#f_item_detail-' + indexs + '-product_line_total_amount').val(result);
}
</script>
It is solving the issue of going back and editing the product and hence updating the line item value as you had suggested.
But if you see the function line_total() it breaks. And the total are not calculated. What do you suggest? How can we use the indexs value or something else. Also, I would be greatful if you could also suggest me how can we display the GST Amount total and Amount Total at the end with a Grand Total (GST Amount Total + Amount Total), I would be really greatful.
I am not good with javascript or jQuery at all.
Upvotes: 1
Views: 813
Reputation: 28522
Whenever your select-box gets change you can simply get closest
tr from that select-box then .find()
to find required inputs and add value there .
Demo Code :
$(document).on('change', 'select', function() {
var selector = $(this).closest("tr") //get closest tr
/* $.ajax({
type: "GET",
url: "<cms:show k_site_link />generate/quotation-ajax.php",
data: "select_id=" + $(this).val(),
async: false
}).done(function(data) {*/
//find your input and add value there
selector.find('.k_element_product_hsn input').val("ac"); //data.product_details[i].product_hsn
selector.find('.k_element_product_price input').val(124); //data.product_details[i].product_price
selector.find('.k_element_product_tax input').val(23); //data.product_details[i].product_tax
selector.find('.k_element_product_line_total_amount input').val(4356); //data.product_details[i].product_line_total_amount
selector.find('.k_element_product_qty input').val(2); //data.product_details[i].product_qty
/*}
})*/
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
<table>
<tbody>
<tr id="newDataRow_f_item_detail" class="newRow even">
<td class="dg-arrange-table-rows-drag-icon"> </td>
<td class="editable k_element_product">
<div style="position:relative;">
<select name="data[xxx][product]" idx="data-xxx-product" id="data-xxx-product">
<option value="-">Select</option>
<option value="3Ply Mask">3Ply Mask</option>
<option value="Laptop i3 4th Gen">Laptop i3 4th Gen</option>
</select>
</div>
</td>
<td class="editable k_element_product_hsn">
<div style="position:relative;"><input type="text" idx="data-xxx-product_hsn" id="data-xxx-product_hsn" name="data[xxx][product_hsn]" value="">
</div>
</td>
<td class="editable k_element_product_qty">
<div style="position:relative;"><input type="text" idx="data-xxx-product_qty" id="data-xxx-product_qty" name="data[xxx][product_qty]" value="">
</div>
</td>
<td class="editable k_element_product_price">
<div style="position:relative;"><input type="text" idx="data-xxx-product_price" id="data-xxx-product_price" name="data[xxx][product_price]" value="">
</div>
</td>
<td class="editable k_element_product_tax">
<div style="position:relative;"><input type="text" idx="data-xxx-product_tax" id="data-xxx-product_tax" name="data[xxx][product_tax]" value="">
</div>
</td>
<td class="editable k_element_product_line_total_amount">
<div style="position:relative;"><input type="text" idx="data-xxx-product_line_total_amount" id="data-xxx-product_line_total_amount" name="data[xxx][product_line_total_amount]" value="">
</div>
</td>
<td class="delete"><input type="checkbox" name="delete[]" value="" id="deleteNULL_STRING" style="display: none;" /><label for="deleteNULL_STRING"> <img src="http://localhost/CTO/GXCPL-Billing/couch/addons/repeatable/tablegear/delete.gif" alt="Delete Row" /></label></td>
</tr>
<tr id="newDataRow_f_item_detail" class="newRow even">
<td class="dg-arrange-table-rows-drag-icon"> </td>
<td class="editable k_element_product">
<div style="position:relative;">
<select name="data[xxx][product]" idx="data-xxx-product" id="data-xxx-product">
<option value="-">Select</option>
<option value="3Ply Mask">3Ply Mask</option>
<option value="Laptop i3 4th Gen">Laptop i3 4th Gen</option>
</select>
</div>
</td>
<td class="editable k_element_product_hsn">
<div style="position:relative;"><input type="text" idx="data-xxx-product_hsn" id="data-xxx-product_hsn" name="data[xxx][product_hsn]" value="">
</div>
</td>
<td class="editable k_element_product_qty">
<div style="position:relative;"><input type="text" idx="data-xxx-product_qty" id="data-xxx-product_qty" name="data[xxx][product_qty]" value="">
</div>
</td>
<td class="editable k_element_product_price">
<div style="position:relative;"><input type="text" idx="data-xxx-product_price" id="data-xxx-product_price" name="data[xxx][product_price]" value="">
</div>
</td>
<td class="editable k_element_product_tax">
<div style="position:relative;"><input type="text" idx="data-xxx-product_tax" id="data-xxx-product_tax" name="data[xxx][product_tax]" value="">
</div>
</td>
<td class="editable k_element_product_line_total_amount">
<div style="position:relative;"><input type="text" idx="data-xxx-product_line_total_amount" id="data-xxx-product_line_total_amount" name="data[xxx][product_line_total_amount]" value="">
</div>
</td>
<td class="delete"><input type="checkbox" name="delete[]" value="" id="deleteNULL_STRING" style="display: none;" /><label for="deleteNULL_STRING"> <img src="http://localhost/CTO/GXCPL-Billing/couch/addons/repeatable/tablegear/delete.gif" alt="Delete Row" /></label></td>
</tr>
</tbody>
</table>
Updated 1 :
You can get index
of tr which is change then using that index we can update that input values .
Updated Jquery code :
$(document).on('change', 'select', function() {
var data = "";
var i = 0;
var indexs = $(this).closest("tr").index();//get index no
console.log(indexs)
$.ajax({
type: "GET",
url: "<cms:show k_site_link />generate/quotation-ajax.php",
data: "select_id=" + $(this).val(),
async: false
}).done(function(data) {
$('#f_item_detail-' + indexs + '-product_hsn').val(data.product_details[i].product_hsn).attr('readonly', true).addClass("form-control");
$('#f_item_detail-' + indexs + '-product_qty').attr('onchange', 'add_number()');
$('#f_item_detail-' + indexs + '-product_price').val(data.product_details[i].product_price).attr('onchange', 'add_number()');
$('input#f_item_detail-' + indexs + '-product_tax').val(data.product_details[i].product_tax).attr('readonly', true).addClass("form-control");
$('#f_item_detail-' + indexs + '-line_tax_amount').attr('readonly', true).addClass("form-control");
$('#f_item_detail-' + indexs + '-product_line_total_amount').val(data.product_details[i].product_line_total_amount).attr('readonly', true).addClass("form-control");
});
});
Update 2 :
You can pass this
as a parameter to your line_total()
then use that to get closest tr index and then do calculation according to that .
Updated Jquery code :
$(document).on('change', 'select', function() {
var indexs = $(this).closest("tr").index();
var selector = $(this); //save selector
var i = 0;
$.ajax({
type: "GET",
url: "<cms:show k_site_link />generate/quotation-ajax.php",
data: "select_id=" + $(this).val(),
async: false
}).done(function(data) {
console.log("de");
$('#f_item_detail-' + indexs + '-product_hsn').val(data.product_details[i].product_hsn).attr('readonly', true).addClass("form-control");
$('#f_item_detail-' + indexs + '-product_qty').attr('onchange', 'line_total(this)'); //pass this here ...
$('#f_item_detail-' + indexs + '-product_price').val(data.product_details[i].product_price).attr('onchange', 'line_total(this)'); //pass this here
$('input#f_item_detail-' + indexs + '-product_tax').val(data.product_details[i].product_tax).attr('readonly', true).addClass("form-control");
$('#f_item_detail-' + indexs + '-line_tax_amount').attr('readonly', true).addClass("form-control");
$('#f_item_detail-' + indexs + '-product_line_total_amount').val(data.product_details[i].product_line_total_amount).attr('readonly', true).addClass("form-control");
line_total(selector); //call this
});
});
function line_total(selector) {
//do same here
var indexs = $(selector).closest("tr").index()
var line_qty = $('input#f_item_detail-' + indexs + '-product_qty').val() != "" ? $('input#f_item_detail-' + indexs + '-product_qty').val() : 1;
var line_tax = $('input#f_item_detail-' + indexs + '-product_tax').val();
var line_cost = $('input#f_item_detail-' + indexs + '-product_price').val();
var line_tax_amount = parseFloat(((line_cost * line_tax) / 100) * line_qty).toFixed(2);
var result = parseFloat((+line_qty * +line_cost) + +line_tax_amount).toFixed(2);
$('#f_item_detail-' + indexs + '-line_tax_amount').val(line_tax_amount).attr('hidden', true);
$('#f_item_detail-' + indexs + '-product_line_total_amount').val(result);
grand_total(); //call this
}
function grand_total() {
var grand = 0;
$(".k_element_product_line_total_amount input").each(function() {
grand += $(this).val() != "" ? parseFloat($(this).val()) : 0
})
$("#grand_total").text(grand + 100); //100 is gst change it...according to your need and change id where you need to display grand total
}
Upvotes: 1
Reputation: 279
So I have been trying to get things on track. Finally, I have been able to do it: The jQuery AJAX code that I was looking for to solve my problem is as below:
var counter = 0;
$(document).ready(function() {
$(".addRow").click(function(){
counter++;
});
});
$(document).on('change','select',function() {
var data = "";
var i = 0;
$.ajax({
type:"GET",
url : "<cms:show k_site_link />generate/quotation-ajax.php",
data:
"select_id="+$(this).val(),
async: false
}).done(function(data) {
$('#f_item_detail-'+ counter +'-product_hsn').val(data.product_details[i].product_hsn);
$('#f_item_detail-'+ counter +'-product_qty').val(data.product_details[i].product_qty);
$('#f_item_detail-'+ counter +'-product_price').val(data.product_details[i].product_price);
$('#f_item_detail-'+ counter +'-product_tax').val(data.product_details[i].product_tax);
$('#f_item_detail-'+ counter +'-product_line_total_amount').val(data.product_details[i].product_line_total_amount);
})
});
I am actually creating a global counter using:
var counter = 0;
$(document).ready(function() {
$(".addRow").click(function(){
var globalcounter = parseFloat(counter);
counter++;
});
});
And then passing the value of the global counter as "counter" to the ajax(). Everytime the "Add Row" is clicked, the counter value in passed then incremented. This helps me in giving the numbers to the id's of each rows input as:
$('#f_item_detail-'+ counter +'-product_hsn').val(data.product_details[i].product_hsn);
Here i in "data.product_details[i]" remains zero because the AJAX returns details for only one product per line-item.
Upvotes: 0