I am creating a dynamic form list and in row there is a subtotal value and what I need is to have a grand total. But my problem is I can't sum all the values.
Here's a bit of my code:
//i created a array that will hold all subtotals
$scope.grand_total = [];
//this function is visible in every row
$scope.subTotal = function($index) {
var total = 0;
angular.forEach($scope.quoteHeader.items[$index], function(value){
angular.forEach(value.items, function(v) {
total += v.unit * v.unit_price;
$scope.grand_total.push({
subtotal: total
});
});
});
return total;
}
//this will process the sum but It didn't work
function computeGrandTotal() {
var total = 0;
angular.forEach($scope.grand_total, function(value) {
console.log(value);
});
}
$scope.grandTotal = function() {
var total = 0.00;
computeGrandTotal(); //call the subtotal function
console.log(computeGrandTotal());
return total;
}
Here's the plnkr: http://plnkr.co/edit/Bfd1e5?p=preview
I hope you can help me with this. Thats all thanks :)
You need to store the total at the given index in the sub_total array then
var quotationList = angular.module('quotation_list', []);
quotationList.controller('quoteList', function($scope) {
$scope.quoteHeader = {};
$scope.quoteHeader = {
items: []
}
$scope.json_output = angular.fromJson($scope.quoteHeader); //display json view
$scope.addParticularHeader = function() {
$scope.quoteHeader.items.push({
particular_name: 'SAMPLE PARTICULAR TITLE',
child_label: {
items: []
}
});
}
$scope.removeQuoteHeader = function($index) {
$scope.quoteHeader.items.splice($index, 1);
}
$scope.addParent = function($index) {
//here we will append the new row
//console.log($scope.quoteHeader.items[$index].child_label);
$scope.quoteHeader.items[$index].child_label.items.push({
particular: 'Sample Particular Name',
unit: 1,
unit_label: 'sqm',
unit_price: 0.00,
unit_subtotal: 0.00,
sublevel: {
items: []
}
});
}
$scope.removeParent = function(parent_id, $index) {
$scope.quoteHeader.items[parent_id].child_label.items.splice($index, 1);
}
$scope.addSubLevel = function(parent_id) {
console.log(parent_id);
}
$scope.grand_total = [];
$scope.subTotal = function($index) {
var total = 0;
angular.forEach($scope.quoteHeader.items[$index], function(value) {
angular.forEach(value.items, function(v) {
total += v.unit * v.unit_price;
});
});
$scope.grand_total[$index] = total;
return total;
}
function computeGrandTotal() {
var total = 0;
//console.log($scope.grand_total);
angular.forEach($scope.grand_total, function(value) {
console.log('total', value);
total += value;
});
return total;
}
$scope.grandTotal = function() {
return computeGrandTotal();
}
});
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet" />
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="//code.angularjs.org/1.3.16/angular.js"></script>
<div class="container">
<h1>Quotation List</h1>
<div ng-app="quotation_list" class="row">
<div ng-controller="quoteList">
<div class="row">
<div class="col-md-12 text-right">
<button ng-click="addParticularHeader()" class="btn btn-primary" type="button">
<span class="fa fa-plus"></span>
Add Particular Header</button>
</div>
</div>
<hr />
<div class="row" ng-repeat="item in quoteHeader.items">
<div class="panel panel-default">
<div class="panel-heading">
<h5 contenteditable="" class="panel-title">{{ item.particular_name }} - {{ $index + 1}} <span ng-click="removeQuoteHeader($index)" class="pull-right btn btn-danger">
<span class="fa fa-times"></span>
Remove</span>
</h5>
<div class="clearfix"></div>
</div>
<div class="panel-body">
<div class="table-responsive">
<table class="table table-bordered">
<thead>
<tr>
<td class="text-center">No.</td>
<td class="text-center">Particulars</td>
<td class="text-center">Unit</td>
<td class="text-center">Unit Label</td>
<td class="text-center">Unit(Price)</td>
<td class="text-center">Unit Price(Php)</td>
<td class="text-center"></td>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in quoteHeader.items[$index].child_label.items">
<td class="text-center">{{ $index + 1 }}</td>
<td class="text-center">
<input type="text" ng-model="item.particular" class="form-control" />
</td>
<td class="text-center">
<input type="number" ng-minlength="1" ng-model="item.unit" class="form-control text-center" />
</td>
<td class="text-center">
<select class="form-control">
<option value="sqm">sqm</option>
<option value="lot">lot</option>
<option value="sets">sets</option>
</select>
</td>
<td class="text-center">
<input type="number" ng-model="item.unit_price" class="form-control text-right" />
</td>
<td class="text-center">
<input type="text" readonly="" value="{{ item.unit * item.unit_price | currency: '₱ ' }}" class="form-control text-right" />
</td>
<td class="text-center">
<button ng-click="addSubLevel($parent.$index)" class="btn btn-primary" type="button">
<span class="fa fa-plus"></span>
</button>
<button ng-click="removeParent($parent.$index, $index)" class="btn btn-danger" type="button">
<span class="fa fa-times"></span>
</button>
</td>
</tr>
<tr>
<td ng-show="!quoteHeader.items[$index].child_label.items.length" class="text-center" colspan="7">
<p>No list yet!</p>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td class="text-center" colspan="6">
<button ng-click="addParent($index)" class="btn btn-primary" type="button">
<span class="fa fa-plus"></span>Add Parent</button>
</td>
<td>
<label>Subtotal: <span>{{ subTotal($index) | currency: '₱ ' }}</span>
</label>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
<div ng-show="!quoteHeader.items.length" class="row text-center">
<p>No particulars yet!</p>
</div>
<div class="pull-right">
<label>Grand Total:</label>
<p>{{ grandTotal() }}</p>
<!--
<input type="text" class="form-control text-right" value="{{ grandTotal() | currency: '₱ ' }}" readonly />
-->
</div>
<div class="clearfix"></div>
</div>
</div>
</div>
Related
I have a table that allow user to add more column OR edit existing column. Inside the existing columns there is dropdown list option for editing.
Like Mentioned in the Image:
I want to export this table in csv or in excel with this dropdown validation options. I tried to implement with export2csv() function but its not getting dropdown.
The output of my export2csv() function:
The output I want:
.html Code :
<div class="card-body">
<div class="table-responsive">
<table class="table dataTable" id="fuelData">
<thead>
<tr>
<th>SNO</th>
<th>Month/Year</th>
<th>Fuel Zone</th>
<th>Fuel Price/Litre</th>
<th>Currency</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{% for f in fuelData%}
<tr id="{{f.id}}">
<td>{{ forloop.counter }}</td>
<td>
<span class="editSpan monthyear">{{f.last_modified}}</span>
<input class="form-control editInput monthyear" type="date" name="monthyear" value="{{f.last_modified}}" style="display: none;">
<small class="text-danger" id="err-monthyear"></small>
</td>
<td>
<span class="editSpan fuel_zone">{{f.fuel_zone}}</span>
<input class="form-control editInput fuel_zone" type="text" name="fuel_zone" value="{{f.fuel_zone}}" style="display: none;">
<small class="text-danger" id="err-fuel_zone"></small>
</td>
<td>
<span class="editSpan fuel_price">{{f.fuel_cost}}</span>
<input class="form-control editInput fuel_price" type="number" name="fuel_price" value="{{f.fuel_cost}}" style="display: none;">
<small class="text-danger" id="err-fuel_price"></small>
</td>
<td>
<span class="editSpan fuel_currency">{{f.currency}}</span>
<select class="form-control editInput fuel_currency" name="fuel_currency" style="display: none;">
{% for c in currency %}
<option value="{{c}}">{{c}}</option>
{% endfor %}
</select>
<small class="text-danger" id="err-fuel_currency"></small>
</td>
<td>
<button type="button" class="btn btn-primary editBtn">Edit</button>
<button type="button" class="btn btn-secondary deleteBtn">Delete</button>
<button type="button" class="btn btn-success saveBtn" style="display: none;">Save</button>
<button type="button" class="btn btn-danger confirmBtn" style="display: none;">Confirm</button>
<button type="button" class="btn btn-secondary cancelBtn" style="display: none;">Cancel</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
Javascript Code :
<script>
function export2csv(){
let data = "";
const tableData = [];
const rows = document.querySelectorAll("table tr");
for (const row of rows) {
const rowData = [];
for (const [index, column] of row.querySelectorAll("th, td").entries()) {
if ((index + 1) % 3 === 0) {
rowData.push('"' + column.innerText + '"');
} else {
rowData.push(column.innerText);
}
}
tableData.push(rowData.join(","));
}
data += tableData.join("\n");
const a = document.createElement("a");
a.href = URL.createObjectURL(new Blob([data], { type: "text/csv" }));
a.setAttribute("download", "data.csv");
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
</script>
How can I get dropdown option in csv after exporting?
Thanks In advance!!
I write down a function which is bulk deletion on table. There is a table with checkbox on every rows, if some one select checkboxs then click on delete button its shows a confirmation modal, if it is close them modal then no action occurs.
In my case when I checked the boxes modal shows correct selected data, and if I then unchecked their is no problem, problem occurs when third time checked it populate previous unchecked data in modal. means checked -> unchecked -> checked.
let newTableData = "";
$('.btn-delete-employees-table-danger').hide();
let modalValue = null;
let selectedID = null;
let selectedRow = ""
let counter = 0;
console.log($('.btndelete'));
$(document).on('click', '.btndelete', function(e) {
$('.btn-delete-employees-table-danger').show();
if ($(this).prop("checked") == true || this.checked) {
counter = counter + 1;
var id = $(this).closest('tr').data('id');
selectedRow = $(`.roww[data-id=${id}]`);
selectedID = $(this).closest('tr').attr('id');
$(this).closest('tr').addClass('deleteselectedrow')
if($(this).closest('tr').addClass('deleteselectedrow')) {
$('.counter-of-selected-emp-modal').html(`${counter} employees will be deleted`)
newTableData += `
<div class="card mt-3" id="emp-${selectedID}">
<div class="d-flex justify-content-between modal-row">
<div>
<h4>${selectedRow[0].cells[1].innerText}</h4>
<p class="light-small-grey-text">ID</p>
</div>
<div>
<h4>${selectedRow[0].cells[2].innerText}</h4>
<p class="light-small-grey-text">Emp Name</p>
</div>
<div>
<h4>${selectedRow[0].cells[3].innerText}</h4>
<p class="light-small-grey-text">Emp DOB</p>
</div>
<div>
<h4>${selectedRow[0].cells[4].innerText}</h4>
<p class="light-small-grey-text">Emp CNIC</p>
</div>
</div>
</div>
`
console.log(newTableData);
}
$('.data-in-modal').html(newTableData);
} else {
counter = counter - 1;
$('.counter-of-selected-emp-modal').html(`${counter} employees will be deleted`)
selectedID = $(this).closest('tr').attr('id');
console.log($(selectedRow[0].cells[0].childNodes[1].checked))
console.log($("#emp-"+selectedID));
$(this).prop('checked', false);
$("#emp-"+selectedID).remove();
$("#emp-"+selectedID).empty();
$(this).prop("checked") == false;
$("#emp-"+selectedID).addClass('d-none')
console.log($('.data-in-modal'));
console.log(newTableData);
}
if(counter == 0 ) {
$('.btn-delete-employees-table-danger').hide();
$('.data-in-modal').html("");
newTableData = '';
}
});
function getandsetdate() {
var date = new Date().toISOString('yyyy-mm-dd').split('T')[0];
var element = document.getElementById('date')
element.value = date
return date
}
// show confirmation modal
$('.shown-modal').on('click', function (e) {
var policy_date_elem = $('input[name="emp_policy_end"]')
policy_date_elem.val(getandsetdate())
policy_date_elem.css('border', '1px #ced4da solid')
$('#showsDependentModal').modal('show');
})
$('#btnDelteYes').click(function () {
$('.deleteselectedrow').remove();
console.log($('.deleteselectedrow'))
console.log($('.deleteselectedrow').prevObject[0]);
$('.btn-delete-employees-table-danger').hide();
newTableData = ""
$('#showsDependentModal').modal('hide');
});
$('.no-btn').click(function () {
$('tr').removeClass('deleteselectedrow')
$('#showsDependentModal').modal('hide');
})
<table class="table table-bordered sortable empy-table" id="table">
<thead class="">
<tr>
<th>
Select
</th>
<!-- <th>check</th> -->
<th>Emp ID</th>
<th>Employee Name</th>
<th>DOB</th>
<th>CNIC</th>
<th class="noExport">Details</th>
</tr>
</thead>
<tbody id="search-table" class="employees_body">
<!-- {% for employee in employees %}
<tr id="{{ employee.id }}" data-id="{{ forloop.counter }}" class="roww">
<td>
<input class="btndelete" type="checkbox" name="employee_id" value="{{ employee.id }}" />
</td>
<td>
{{employee.id}}
</td>
<td>
{{employee.first_name}} {{employee.last_name}}
</td>
<td>
{{employee.date_of_birth}}
</td>
<td>
{{employee.cnic}}
</td>
<td class="noExport">
<a class="text-dark" href="{% url 'smartbenefits:employee_profile' employee.id %}">
<button class="button-detail"><span class="fa fa-info-circle"></span></button>
</a>
</td>
</tr>
{% endfor %} -->
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="modal hide fade" id="showsDependentModal" tabindex="-1" aria-labelledby="showssDependentModal" aria-hidden="true">
<div class="modal-dialog modal-lg modal-dialog-centered">
<div class="modal-content modal-secondary">
<div class="px-4 pt-5 w-100">
<div class="d-flex justify-content-between w-100">
<div class="">
<h4>Please confirm if you want to delete the below employees?</h4>
<p class="counter-of-selected-emp-modal"></p>
</div>
<i class="fa fa-window-close dependent-close-icons-modal no-btn" id="modal-dismiss" data-bs-dismiss="modal" aria-label="Close"></i>
</div>
</div>
<div class="modal-body">
<div class="data-in-modal ">
</div>
<div class="policy-end w-25 mt-3">
<!-- <input type="text" name="emp_policy_end" readonly vaule="" /> -->
<label class="date-detail" for="emp_policy_end">Policy End Date. <span
class="fa fa-info-circle"></span></label>
<span class="hover-message">Policy End date will be same as the current date. For further queries,
contact our ops team</span>
<input id="date" type="date" name="emp_policy_end" readonly />
</div>
</div>
<div class="modal-footer">
<button class="button-secondary active" id="btnDelteYes">Confirm</button>
</div>
</div>
</div>
</div>
I wrote a code for a shopping cart. In that for each change in quantity value (either increasing or decreasing) there should be a change in the price. I tried to implement this for a decreasing price with respect to the quantity. I can change the quantity but I am not able to change the price field because the price still gives me the type of object as I console.log. Can anyone point out what I am doing wrong?
Below is the code:
product.html
<tr>
<td class="product-thumbnail">
<img src="images/cloth_1.jpg" alt="Image" class="img-fluid">
</td>
<td class="product-name">
<h2 class="h5 text-black">Top Up T-Shirt</h2>
</td>
<!-- The price -->
<td>$49.00</td>
<td>
<div class="input-group mb-3" style="max-width: 120px;">
<div class="input-group-prepend">
<button class="btn btn-outline-primary js-btn-minus" type="button">−</button>
</div>
<input type="text" class="form-control text-center" value="1" placeholder="" aria-label="Example text with button addon" aria-describedby="button-addon1">
<div class="input-group-append">
<button class="btn btn-outline-primary js-btn-plus" type="button">+</button>
</div>
</div>
</td>
<td>
<div class="price"></div>
</td>
<td>X</td>
</tr>
<tr>
<td class="product-thumbnail">
<img src="images/cloth_2.jpg" alt="Image" class="img-fluid">
</td>
<td class="product-name">
<h2 class="h5 text-black ">Polo Shirt</h2>
</td>
<td>$49.00</td>
<td>
<div class="input-group mb-3" style="max-width: 120px;">
<div class="input-group-prepend">
<button class="btn btn-outline-primary js-btn-minus" type="button">−</button>
</div>
<input type="text" class="form-control text-center" value="1" placeholder="" aria-label="Example text with button addon" aria-describedby="button-addon1">
<div class="input-group-append">
<button class="btn btn-outline-primary js-btn-plus" type="button">+</button>
</div>
</div>
</td>
<td>
<div class="price">8</div>
</td>
<td>X</td>
</tr>
main.js
<script>
$('.js-btn-minus').on('click', function(e)
{
e.preventDefault();
if ( $(this).closest('.input-group').find('.form-control').val() !=0 && $(this).closest('.input-group').find('.form-control').val() >0)
{
$(this).closest('.input-group').find('.form-control').val(parseInt($(this).closest('.input-group').find('.form-control').val()) - 1);
var va = parseInt($(this).closest('.input-group').find('.form-control').val());
va = (parseInt(va));
this.a = va;
console.log(this.a);
var price = $(this).closest('tr').find('.price');
console.log(price.val(parseInt(this.a)));
}
}
</script>
use price.html or price.text instead of price.val and then remember, input get value by .val() but other element get by .html() or .text()
First thing is that your table is not well structured. Second thing is that your requirement is not exactly clear to me.
Thought I assume you want to increase or decrease the price where the class is price.
You are receiving the whole element as you are using val() and it is always going to be the object.
If you could tell the exact issue/requirement, I can help you out.
$('.js-btn-minus').on('click', function(e)
{
e.preventDefault();
var next_val = parseInt($(this).closest('.input-group').find('.form-control').val()) - 1;
if (next_val < 0){
next_val = 0
$(this).closest('.input-group').find('.form-control').val(0)
}
else{
$(this).closest('.input-group').find('.form-control').val(next_val);
var existing_value = $(this).closest('tr').find('.price').html()
if ((existing_value || '') == ''){
$(this).closest('tr').find('.price').html(next_val)
}
else{
$(this).closest('tr').find('.price').html(existing_value - 1)
}
}
// Price updates
//var current_price = parseInt($(this).closest('.input-group').parent().prev('td').html().replace('$', ''))
//var final_price = current_price - next_val;
});
$('.js-btn-plus').on('click', function(e)
{
e.preventDefault();
var next_val = parseInt($(this).closest('.input-group').find('.form-control').val()) + 1;
if (next_val < 0){
next_val=0;
$(this).closest('.input-group').find('.form-control').val(0)
}
else{
$(this).closest('.input-group').find('.form-control').val(next_val);
var existing_value = parseInt($(this).closest('tr').find('.price').html())
if ((existing_value || '') == ''){
$(this).closest('tr').find('.price').html(next_val)
}
else{
$(this).closest('tr').find('.price').html(existing_value + 1)
}
}
// Price updates
//var current_price = parseInt($(this).closest('.input-group').parent().prev('td').html().replace('$', ''))
//var final_price = current_price + 1
//console.log(final_price)
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<td class="product-thumbnail">
<img src="images/cloth_1.jpg" alt="Image" class="img-fluid">
</td>
<td class="product-name">
<h2 class="h5 text-black">Top Up T-Shirt</h2>
</td>
<!-- The price -->
<td class="current_price">$49.00</td>
<td>
<div class="input-group mb-3" style="max-width: 120px;">
<div class="input-group-prepend">
<button class="btn btn-outline-primary js-btn-minus" type="button">−</button>
</div>
<input type="text" class="form-control text-center" value="1" placeholder="" aria-label="Example text with button addon" aria-describedby="button-addon1">
<div class="input-group-append">
<button class="btn btn-outline-primary js-btn-plus" type="button">+</button>
</div>
</div>
</td>
<td>
<div class="price"></div>
</td>
<td>X</td>
</tr>
<tr>
<td class="product-thumbnail">
<img src="images/cloth_2.jpg" alt="Image" class="img-fluid">
</td>
<td class="product-name">
<h2 class="h5 text-black ">Polo Shirt</h2>
</td>
<td class="current_price">$49.00</td>
<td>
<div class="input-group mb-3" style="max-width: 120px;">
<div class="input-group-prepend">
<button class="btn btn-outline-primary js-btn-minus" type="button">−</button>
</div>
<input type="text" class="form-control text-center" value="1" placeholder="" aria-label="Example text with button addon" aria-describedby="button-addon1">
<div class="input-group-append">
<button class="btn btn-outline-primary js-btn-plus" type="button">+</button>
</div>
</div>
</td>
<td>
<div class="price">8</div>
</td>
<td>X</td>
</tr>
</table>
I'm new to AngularJs and I'm stuck in multi ng-repeat.
HTML CODE
<table class="table table-bordered tdPaddingNull verTop">
<thead>
<tr>
<th width="200px">Product Details </th>
<th width="250px">Current Availability</th>
<th width="200px">Batch </th>
<th>Quantity</th>
<th>Rate INR </th>
<th>Amt. INR</th>
<th>Converted Amount</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="(i,product) in listproducts track by $index">
<td style="padding: 7px;">
<input auto-complete ui-items="prductdetail" ng-model="formData.product_name[i]" class="form-control form-white" my-id="{{i}}"/>
<input id="product_id{{i}}" placeholder="productid" type="hidden" value="" ng-model="formData.product_id[i]" my-id="{{i}}"/>
<a ng-click="addProductBatch()" title="Add Another Batch Quantity" style="float:right;"><i class="fa fa-plus" aria-hidden="true"></i> ADD BATCH </a>
</td>
<td class="line-item-column item-currentavail transferorder-lineitem">
<div class="row text-muted font-sm">
<div class="col-md-6">
Source Stock
</div>
<div class="separationline col-md-6">
Destination Stock
</div>
</div>
<div class="row font-xs">
<div class="col-md-6">
0.00 Units
</div>
<div class="separationline col-md-6">
0.00 Units
</div>
</div>
</td>
<td style="padding: 7px;">
<div style="display:inline-block;width:100%;" ng-repeat="addBatch in listAddbatches">
<select class="form-control form-white selectNor" ng-model="formData.batch_id[i]" ng-change="changedBatchValue(formData.batch_id)" style="margin-bottom: 5px;width: 88%;float: left;">
<option value="">Select Batch</option>
<option value="{{blist.batch_id}}" ng-repeat="blist in batchList">{{blist.batch_number}}</option>
</select>
<a class="inputTabel1" ng-click="removeBatch($index)" title="Remove Batch" style="float:left;margin-left: 4px;"> <i class="fa fa-times-circle-o" aria-hidden="true" ></i>
</a>
</div>
</td>
<td style="padding: 7px;">
<input class="form-control form-white" type="text" value="" ng-model="formData.product_count[i]" ng-repeat="addBatch in listAddbatches" style="margin-bottom: 5px;"/>
</td>
<td style="padding: 7px;">
<input class="form-control form-white " placeholder="Selling Price" type="text" value="0.00" ng-model="formData.sel_inr_rate[i]">
</td>
<td>
<input class="form-control form-white form-Tabel" placeholder="Amount in INR" type="text" value="0.00" ng-model="formData.sel_inr_amount[i]" readonly />
</td>
<td class="Amount ">
<input class="form-control form-white form-Tabel" placeholder="" type="text" value="0.00" ng-model="formData.exc_total_amount[i]" readonly />
<button class="inputTabel" ng-click="removeProduct($index)"> <i class="fa fa-times-circle-o" aria-hidden="true"></i>
</button>
</td>
</tr>
</tbody>
</table>
ANGULAR CODE
/****************ADD ANOTHER BATCH QUANTITY**************/
$scope.addAnotherProduct = function(listproducts,$event) {
newItemNo = $scope.listproducts.length+1;
$scope.listproducts.push({'batch_id[newItemNo]':'','product_count[newItemNo]':''});
};
$scope.removeProduct = function(index) {
/*var lastItem = $scope.listproducts.length-1;
$scope.listproducts.splice(lastItem);
$scope.listAddbatches = '';*/
$scope.listproducts.splice(index,1);
};
$scope.removeBatch = function(index) {
/*var lastItem = $scope.listAddbatches.length-1;
$scope.listAddbatches.splice(lastItem);
$scope.listAddbatches = '';*/
$scope.listAddbatches.splice(index,1);
};
$scope.addProductBatch = function() {
var newItemNo = $scope.listAddbatches.length+1;
$scope.listAddbatches.push({'id':'batch'+newItemNo});
};
Here when I click ADD ANOTHER PRODUCT it should create an entire row in the table without the columns of Batch and Quantity, but now it's appearing as it in before row created.
Then when I click ADD BATCH it should create under the table column Batch and Quantity of the corresponding row, but now it's adding in all the rows and when I remove added batch, it should remove the corresponding batch, but now it's removing the last added batch.
The same happens when I remove added product (Entire Row), it should remove the corresponding row of the product but now it's removing lastly added Product row.
How can I fix all the aforementioned issues?
Please help me
There are multiple issues with your approach:
1) You are using a global array listAddbatches but you want to add the batches by product, so why shouldn't you use product.listAddbatches array?
2) When using track by $index you will not able to delete correct element from array or object since compiler directive is not re-compiling the element when its data attribute changes.
3) Using array length to generate id like var newItemNo = $scope.listAddbatches.length + 1; is not a good idea since the array length could change (when removing items) in a way that you will have the same ids for different elements.
4) This line is very strange {'batch_id[newItemNo]':'','product_count[newItemNo]':''}, since you are calculating newItemNo, but this is a simple string 'batch_id[newItemNo]'. Why do you need this?
5) Do not recommend to use $index to remove items, since it could point to some other element in case of filtering.
Your code could like this (simplified version), hope this helps:
angular.module('plunker', [])
.controller('MainCtrl', function($scope) {
$scope.listproducts = [];
$scope.addAnotherProduct = function(listproducts) {
listproducts.push( {
listAddbatches: []
});
};
$scope.removeProduct = function(product) {
var index = $scope.listproducts.indexOf(product);
if (index >= 0)
$scope.listproducts.splice(index, 1);
};
$scope.removeBatch = function(product, batch) {
var index = product.listAddbatches.indexOf(batch);
if (index >= 0)
product.listAddbatches.splice(index, 1);
};
$scope.addProductBatch = function(product) {
product.listAddbatches.push({ });
};
});
<script src="https://code.angularjs.org/1.6.4/angular.js" ></script>
<html ng-app="plunker">
<body ng-controller="MainCtrl">
<table class="table table-bordered tdPaddingNull verTop">
<thead>
<tr>
<th width="200px">Product Details </th>
<th width="250px">Current Availability</th>
<th width="200px">Batch </th>
<th>Quantity</th>
<th>Rate INR </th>
<th>Amt. INR</th>
<th>Converted Amount</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="(i, product) in listproducts">
<td style="padding: 7px;">
<input auto-complete ui-items="prductdetail" ng-model="formData.product_name[i]" class="form-control form-white" my-id="{{i}}"/>
<input id="product_id{{i}}" placeholder="productid" type="hidden" value="" ng-model="formData.product_id[i]" my-id="{{i}}"/>
<a ng-click="addProductBatch(product)" title="Add Another Batch Quantity" style="float:right;"><i class="fa fa-plus" aria-hidden="true"></i> ADD BATCH </a>
</td>
<td class="line-item-column item-currentavail transferorder-lineitem">
<div class="row text-muted font-sm">
<div class="col-md-6">
Source Stock
</div>
<div class="separationline col-md-6">
Destination Stock
</div>
</div>
<div class="row font-xs">
<div class="col-md-6">
0.00 Units
</div>
<div class="separationline col-md-6">
0.00 Units
</div>
</div>
</td>
<td style="padding: 7px;">
<div style="display:inline-block;width:100%;" ng-repeat="addBatch in product.listAddbatches">
<select class="form-control form-white selectNor" ng-model="formData.batch_id[i]" ng-change="changedBatchValue(formData.batch_id)" style="margin-bottom: 5px;width: 88%;float: left;">
<option value="">Select Batch</option>
<option value="{{blist.batch_id}}" ng-repeat="blist in batchList">{{blist.batch_number}}</option>
</select>
<a class="inputTabel1" ng-click="removeBatch(product, addBatch)" title="Remove Batch" style="float:left;margin-left: 4px;"> <i class="fa fa-times-circle-o" aria-hidden="true" ></i>
</a>
</div>
</td>
<td style="padding: 7px;">
<input class="form-control form-white" type="text" value="" ng-model="formData.product_count[i]" ng-repeat="addBatch in product.listAddbatches" style="margin-bottom: 5px;"/>
</td>
<td style="padding: 7px;">
<input class="form-control form-white " placeholder="Selling Price" type="text" value="0.00" ng-model="formData.sel_inr_rate[i]">
</td>
<td>
<input class="form-control form-white form-Tabel" placeholder="Amount in INR" type="text" value="0.00" ng-model="formData.sel_inr_amount[i]" readonly />
</td>
<td class="Amount ">
<input class="form-control form-white form-Tabel" placeholder="" type="text" value="0.00" ng-model="formData.exc_total_amount[i]" readonly />
<button class="inputTabel" ng-click="removeProduct(product)"> <i class="fa fa-times-circle-o" aria-hidden="true"></i>
</button>
</td>
</tr>
</tbody>
</table>
<button ng-click="addAnotherProduct(listproducts)">Add Another Product</button>
</body>
</html>
I am doing an exercise to learn JavaScript. I am having issues making my program dynamic. What I want to do here is:
Create two input to let the user set up the new product data.
Create a button. This button will have assigned a click event that will: 1- Get the data from the inputs. 2- Create a new product row with the data we stored.
Be able to delete all items and decrease total price based on the price of reminding item. In case there is no item, total price should be 0.
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Shoping</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="css/style.css">
<script src="js/index.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
</head>
<body>
<div class="container">
<header>
<h1 class="h1 text-center mb">Shoping<span class="glyphicon glyphicon-shopping-cart" aria-hidden="true"></span></h1>
</header>
<table class="table mb">
<thead>
<tr>
<th>Products:</th>
<th>Price:</th>
<th>Quantity:</th>
<th>Total:</th>
<th>
</th>
</tr>
</thead>
<tbody id="soyTBody">
<tr id="itemSubject">
<th scope="row"><span id="productName">T-Shirts</span></th>
<td class="price1"> <span class="dolar">$</span><span id="product">15</span></td>
<td class="qty1">
<form class="form-inline">
<div class="form-group">
<label for="inputQty">QTY</label>
<input type="text" id="qty" class="form-control mx-sm-3" maxlength="3" aria-describedby="qtyItem1">
</div>
</form>
</td>
<td <span class="dolar">$</span><span id="total">0.00</span></td>
<td class="text-right">
<button class="delate btn btn-danger" type="button" onclick="removeItem()" value="delate">
<input id ="delateButton" class="delateItem" type="button" value="Delate">
</button>
</td>
</tr>
<tr id="itemSubject2">
<th scope="row"><span id="productName">Stickers</span></th>
<td class="price2"> <span class="dolar">$</span><span id="product2">2</span></td>
<td class="qty2">
<form class="form-inline">
<div class="form-group">
<label for="inputQty">QTY</label>
<input type="text" id="qty2" class="form-control mx-sm-3" maxlength="3" aria-describedby="qtyItem2">
</div>
</form>
</td>
<td <span class="dolar">$</span><span id="total2">0.00</span></td>
<td class="text-right">
<button class="delate btn btn-danger" type="button" onclick="removeItem2()" value="delate">
<input id ="delateButton" class="delateItem" type="button" value="Delate">
</button>
</td>
</tr>
<!-- <tr>
<th scope="row">Stickers</th>
<td class="price2">$1</td>
<td class="qty2">
<form class="form-inline">
<div class="form-group">
<label for="inputPassword4">QTY</label>
<input type="text" id="qty2text" class="form-control mx-sm-3" aria-describedby="passwordHelpInline">
</div>
</form>
</td>
<td class="total-2">$0.00</td>
<td class="text-right">
<button class="delate btn btn-danger" type="button" value="delate">
<span class="delateButton"><strong>Delate</strong></span>
</button>
</td>
</tr> -->
<!-- <tr>
<th scope="row">Flags</th>
<td class="price3">$2</td>
<td class="qty3"><form class="form-inline">
<div class="form-group">
<label for="inputPassword4">QTY</label>
<input type="text" id="qty3text" class="form-control mx-sm-3" aria-describedby="passwordHelpInline">
</div>
</form>
</td>
<td class="total3">$0.00</td>
<td class="text-right">
<button class="delate btn btn-danger" type="button" value="delate">
<span class="delateButton"><strong>Delate</strong></span>
</button>
</td>
</tr> -->
</tbody>
</table>
<div class="row text-right">
<button class="delate btn btn-success" onclick="getPrice();getPrice2();totalPrice2()" type="submit" value="calculatePriceButton" >
<input id ="calc-prices-button" class="calculator" type="button" value="Calculate Prices">
<!-- <span class="delateButton"><strong>Calculate Prices</strong></span> -->
</button>
</div>
<h2 class="text-center">Total Price: $<span id="totalPrice"></span></h2>
</div>
</body>
</html>
JS:
// qty
function getQty() {
var qty = document.querySelector("#qty").value;
document.querySelector("#total").innerHTML = qty;
return qty;
}
getQty();
// qty2
function getQty2() {
var qty2 = document.querySelector("#qty2").value;
document.querySelector("#total2").innerHTML = qty2;
return qty2;
}
getQty();
// Price
function getPrice() {
var price = parseInt(document.querySelector("#product").innerHTML);
document.querySelector("#total").innerHTML = price * getQty();
}
getPrice();
// Price 2
function getPrice2() {
var price2 = parseInt(document.querySelector("#product2").innerHTML);
document.querySelector("#total2").innerHTML = price2 * getQty2();
}
getPrice2();
// total Price
function totalPrice2() {
var total = parseInt(document.querySelector("#total").innerHTML);
var total2 = parseInt(document.querySelector("#total2").innerHTML);
document.querySelector("#totalPrice").innerHTML = total + total2;
}
totalPrice2();
//Romove Item
function removeItem() {
var remove = document.querySelector("#itemSubject").remove("itemSubject");
// setTimeout(function() { alert("Your shopping cart is empty"); }, 1000);
}
removeItem();
function removeItem2() {
var remove = document.querySelector("#itemSubject2").remove("itemSubject2");
// setTimeout(function() { alert("Your shopping cart is empty"); }, 1000);
}
removeItem2();
For your getPrice() and getPrice2() functions, we can make them dynamic by changing the following:
var price = parseInt(document.querySelector("#product").innerHTML);
and
var price2 = parseInt(document.querySelector("#product2").innerHTML);
These lines looks for elements with static names, instead we should give all inputs a common class name and loop through them. That way, we don't have to rely on static element IDs. For example, if we gave each input the class 'quantityinput', we can do the following:
var elements = document.getElementsByClassName("quantityinput");
for(var i=0; i<elements.length; i++) {
// Select this element and get its quantity
var this_total = elements[i].value;
// Get the price for this element by selecting the price td, then its second child
var this_price = elements[i].parentElement.parentElement.parentElement.previousSibling.childNodes[2].value;
// Select the total label for this row
var this_total_label = elements[i].parentElement.parentElement.parentElement.childNodes[1];
// Now update the total label for this row by multiplying the price and the quantity
this_total_label.value = this_total * this_price;
}
Now we don't have to worry about a certain row missing, since we iterate through all existing rows. A similar approach can be taken when calculating the total price for all rows, just loop through each rows total price, add them together then assign the total to the total price label.