Getting total sum of rows and adding and removing rows using knockoutjs - javascript

I am fairly new to knockoutjs. I am creating a simple table and trying to sum up all the values in the "total" column. Plus, I am also implementing "Add column" and "Remove Column" functionalities using knockoutjs.
The problem is that both the Add and Remove funcitonalities and not working. Plus,the "TotalSurcharge" value is not displaying on the UI.
Here's my js:
// Class to represent a row in the table
function addMaterial() {
this.name = ko.observable("");
this.quantity = ko.observable("");
this.rate = ko.observable(0);
this.formattedTotal = ko.computed(function() {
return this.rate() * this.quantity();
}, this);
}
function documentViewModel(){
var self = this;
//create a mateirals array
self.materials = ko.observableArray([
new addMaterial()
]);
// Computed data
self.totalSurcharge = ko.computed(function() {
var total = 0;
for (var i = 0; i < self.materials().length; i++)
total += self.materials()[i].formattedTotal();
return total;
});
// Operations
self.addMaterial = function() {
self.materials.push(new addMaterial());
}
self.removeMaterial = function(material) { self.materials.remove(material) }
}
ko.applyBindings(new documentViewModel());
Here's my HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Bootstrap Example</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
<script type='text/javascript' src='knockout-2.2.0.js'></script>
</head>
<body>
<div class="container">
<table class="table table-bordered">
<thead>
<tr>
<th>Item</th>
<th>Quantity </th>
<th>Rate</th>
<th>Total</th>
</tr>
</thead>
<tbody "foreach: materials">
<tr class="info">
<td><input data-bind="value: name" /></td>
<td><input data-bind="value: quantity" /></td>
<td><input data-bind="value: rate" /></td>
<td data-bind="text: formattedTotal"></td>
<td>Remove</td>
</tr>
</tbody>
</table>
<button data-bind="click: addMaterial, enable: materials().length < 5">Add Row</button>
<h3 data-bind="visible: totalSurcharge() > 0">
Total surcharge: $<span data-bind="text: totalSurcharge().toFixed(2)"></span>
</h3>
</div>
</body>
<script type='text/javascript' src='application.js'></script>
</html>
I checked the console error on the browser but am not getting any error. Any idea what am I doing wrong?

I think you intended to bind the materials to the table body, this is not right:
<tbody "foreach: materials">
It should be:
<tbody data-bind="foreach: materials">
Once that is fixed, everything else appears to work.
fiddle

Related

Display "no results found" if there is no matching search text input on the table

I saw this block of code from w3schools and it works perfectly fine. My only issue is that, if the inputted text is not present on the table, it doesn't display anything.
Here's the script code:
$(document).ready(function() {
$('#searchBar').on('keyup', function() {
var value = $(this).val().toLowerCase();
$('#tableData tr').filter(function() {
$(this).toggle($(this).text().toLowerCase().indexOf(value) > -1)
});
});
});
Here's the link to the w3schools article that I am talking about:
https://www.w3schools.com/bootstrap/bootstrap_filters.asp
I'd like to display a text saying "No results found" if there are no search results.
Here my solution for your problem I think this is the optimal solution for your problem.
Here the HTML which I get from the link you provided of w3school I added here a new row in HTML , little style and some conditional line in the JS code
<!DOCTYPE html>
<html lang="en">
<head>
<title>Bootstrap Example</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
<style>
.no-data {
display: none;
text-align: center;
}
</style>
</head>
<body>
<div class="container">
<h2>Filterable Table</h2>
<p>Type something in the input field to search the table for first names, last names or emails:</p>
<input class="form-control" id="myInput" type="text" placeholder="Search..">
<br>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Email</th>
</tr>
</thead>
<tbody id="myTable">
<tr>
<td>John</td>
<td>Doe</td>
<td>john#example.com</td>
</tr>
<tr>
<td>Mary</td>
<td>Moe</td>
<td>mary#mail.com</td>
</tr>
<tr>
<td>July</td>
<td>Dooley</td>
<td>july#greatstuff.com</td>
</tr>
<tr>
<td>Anja</td>
<td>Ravendale</td>
<td>a_r#test.com</td>
</tr>
<tr class="no-data">
<td colspan="4">No data</td>
</tr>
</tbody>
</table>
<p>Note that we start the search in tbody, to prevent filtering the table headers.</p>
</div>
<script>
$(document).ready(function(){
$("#myInput").on("keyup", function() {
let check = true;
var value = $(this).val().toLowerCase();
$("#myTable tr").filter(function() {
$(this).toggle($(this).text().toLowerCase().indexOf(value) > -1)
if($(this).text().toLowerCase().indexOf(value) > -1){
check = false;
$('.no-data').hide();
}
});
if(check){
$('.no-data').show();
}
});
});
</script>
</body>
</html>
the new row I added in HTML for showing "No data" is here:
<tr class="no-data">
<td colspan="4">No data</td>
</tr>
style for the new row
.no-data {
display: none;
text-align: center;
}
I added a some new conditional line in JS and after adding those the JS code is :
$(document).ready(function(){
$("#myInput").on("keyup", function() {
let check = true;
var value = $(this).val().toLowerCase();
$("#myTable tr").filter(function() {
$(this).toggle($(this).text().toLowerCase().indexOf(value) > -1)
if($(this).text().toLowerCase().indexOf(value) > -1){
check = false;
$('.no-data').hide();
}
});
if(check){
$('.no-data').show();
}
});
});
Hope your problem is solved have a nice day .

Jquery datatable how to get parent data from child

I have a jquery datatable of something like this
when i click the plus icon, it will show 2 buttons the capabilities and reimbursement, what I want is when i click the capabilities button, I want to get the parent row which are name, all and etc. Is that possible? I tried several method but it doesn't work.
What I tried is
function set_credentials(el) {
var tr = $(el).closest('tr').parents('tr');
var prevtr = tr.prev('tr')[0];
console.log(prevtr)
But i get the html dom.
I think I almost got it but i need some help. Thanks
Is this what you want? I console.log(name) for the result.
Example below
$("#example").on("click", set_credentials);
function set_credentials(event) {
if (event.target.tagName === "BUTTON") {
var tr = $(event.target).closest("tr");
var prevtr = tr.prev();
var name = prevtr.find("td.mws_name").text();
console.log(name);
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<title>Document</title>
</head>
<body>
<div>
<table id="example">
<thead>
<th>name</th>
<th>date</th>
<th>button</th>
</thead>
<tbody>
<tr>
<td class="mws_name">joe</td>
<td>2011-1-1</td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td><button>set</button></td>
</tr>
<tr>
<td class="mws_name">Sam</td>
<td>2011-5-1</td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td><button>set</button></td>
</tr>
</tbody>
</table>
</div>
</body>
</html>

How to get element id using v-for vuejs directive?

I'm a vue.js beginner, so I need help.
I write an HTML page which show a list of object in a simple table.
The table is made by a script which get a JSON object from a servlet and shows it using a v-for directive.
In each row of the table, there is a button that the user can click to book the object wrote in the corresponding row, using a form.
The problem is that I don't know how to get the object's information correspondent to the clicked line to put it in the form's fields.
This is the code:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Repetition - catalog</title>
<meta charset="UTF-8" name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="style2.css" />
</head>
<body>
<header><h1>REPETITIONS.com</h1></header>
<div id="app" class="float-container" style="height: 80%">
<table class="catalog-table">
<thead>
<tr>
<th style="width: 200px">Corso</th>
<th style="width: 250px">Docente</th>
<th></th>
</tr>
</thead>
<tbody>
<tr v-for="rep in reps">
<td>{{rep.teacherName}} {{rep.teacherSurName}}</td>
<td>{{rep.course}}</td>
<td>
<form action="/Repetition/controller/ServletController" method="post" id="i">
<input type="hidden" name="operation" value="booking">
<input type="hidden" name="id_t" value="rep.getId_teac"> <---set the value of the current row
<input type="hidden" name="id_c" value="rep.getId_cor"> <---set the value of the current row
<button type="submit">Book</button>
</form>
</td>
</tr>
</tbody>
</table>
</div>
<footer>xxxxxxx</footer>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script>
var app = new Vue ({
el: '#app',
data: {
repetitions: [],
link: '/Repetition/ServletController?operation=catalog&device=x'
},
mounted(){
this.getRepetitions()
},
methods:{
getRepetitions: function(){
var self = this;
$.get(this.link, function(data) {
self.repetitions = data;
});
}
}
});
</script>
</body>
</html>
Alternatively the form request could be manage with another script, but there would be the same problem.

Calculate the sum of input values in the last column of table in javascript

Tying to sum up the dynamic input values in the last column of my table. If I hard code the number values then the calculation works just fine. If I input the values my self using a I get NaN
Ive used
My html table is added upon load and the rows are added as needed via a button.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<table id='table' border="1">
<tr>
<th>RO#</th>
<th>Work</th>
<th>Time</th>
</tr>
<tr>
<td>615235</td>
<td>lof, rotate</td>
<!-- <td>23</td> -->
<td><input type="number" /></td>
</tr>
<tr>
<td>6154879</td>
<td>engine, trans</td>
<!-- <td>23</td> -->
<td><input typ="number" /></td>
</tr>
<tr>
<td>6158978</td>
<td>rotate, serp belt, timing belt</td>
<!-- <td>23</td> -->
<td><input type="number" /></td>
</tr>
</table>
<br>
<button onclick='calculate()'>Calculate</button>
<script>
function calculate() {
let tbl = document.getElementById('table'),
sumVal = 0;
for (let i = 1; i < tbl.rows.length; i++) {
sumVal = sumVal + parseInt(tbl.rows[i].cells[2].input);
}
console.log(sumVal);
}
</script>
</body>
</html>
I get NaN when using the <td><input type="number or type="text"><td> code
The problem is that the input property does not exist in tbl.rows[i].cells[2]. Honestly, I don't know if it's possible to get the input values from Table cells Collection that you're trying to utilize.
I suggest this approach, using querySelectorAll in which we specify the inputs we'd like to get data from:
function calculate() {
let tbl = document.querySelectorAll("table input[type='number']"),
sumVal = 0;
for (let i = 0; i < tbl.length; i++) {
sumVal += Number(tbl[i].value);
}
console.log(sumVal);
}

How to change Background color of table row based on respective cell data using angularjs?

I want to change Background color of row based on cell data, like if it matches first four characters from table cell "td", then row should change its color to red.
here is my example, it is working but it takes whole cell data.but i want row color should change once it matches first four characters from cell.
<style>
.bgRed{
background-color:red;
}
</style>
<body ng-app="myApp">
<div ng-controller="myController">
<div class="container" style="margin-top:40px;">
<div class="row">
{{error}}
<div class="col-md-6">
<table class="table table-bordered table-condensed">
<thead>
<tr>
<th>Name</th>
<th>Class Name</th>
<th>Roll No</th>
<th>Email</th>
</tr>
</thead>
<tbody ng-repeat="std in students">
**<tr ng-class="{'bgRed': std.Name === 'Prash'}>**
<td>{{std.Name}}</td>
<td>{{std.ClassName}}</td>
<td>{{std.RollNo}}</td>
<td>{{std.Email}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</body>
and my table is
Table row should change to red if table cell data "Prash or Prashant" matches.instead of taking "Prashant Olekar"
how to achive this please help. Thank you
Using substring you can trim the characters of the string,
here I'm creating one more variable(filed) "trimmed_name" which is a substring of your "name" which gives you first 4 characters of your string "name".
<tr ng-repeat="std in students" ng-init="trimName(std)">
<td ng-class="{'bgRed': std.trimmed_name === 'Prash', 'bgBlue': std.trimmed_name === 'Pavi', 'bgBlack' : std.trimmed_name === 'Pava'}">{{std.Name}}</td>
<td>{{std.ClassName}}</td>
<td>{{std.RollNo}}</td>
<td>{{std.Email}}</td>
</tr>
In Css add respective colours for respective classes
in your controller
$scope.trimName = function (std) {
std.trimmed_name = std.Name.substring(0, 4);
return std;
};
Just in case if 'Prash' dose not work use {'bgRed': std.trimmed_name === "Prash"}
Hope it helps you.
you can use a custom filter to set class according to condition of your row data,
html
<tbody ng-repeat="std in students | filter:filterColor">
<tr class="{{std.class}}">
<td>{{std.Name}}</td>
<td>{{std.ClassName}}</td>
<td>{{std.RollNo}}</td>
<td>{{std.Email}}</td>
</tr>
</tbody>
js
$scope.filterColor = function (item) {
if (your condition) {
item.class = 'your class';
}
else
item.class = 'some other class';
return true;
};
I have got solution to my question with the help of Rajat, here is my code. but it only matches characters from 0th Position.
<head>
<title></title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="Content/bootstrap.min.css" rel="stylesheet" />
<script src="Scripts/angular.min.js"></script>
<script src="Scripts/App/app.js"></script>
<style>
.bgRed {
background-color: #cfeaff;
}
</style>
</head>
<body ng-app="myApp">
<div ng-controller="myController">
<div class="container" style="margin-top:40px;">
<div class="row">
{{error}}
<div class="col-md-6">
<table class="table table-bordered table-condensed">
<thead>
<tr>
<th>Name</th>
<th>Class Name</th>
<th>Roll No</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="std in students" ng-init="trimName(std)" ng-class="{bgRed: std.trimmed_name === 'Pras'}">
<td>{{std.Name}}</td>
<td>{{std.ClassName}}</td>
<td>{{std.RollNo}}</td>
<td>{{std.Email}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</body>
</html>
and In Controller
/// <reference path="../angular.min.js" />
var myApp = angular.module('myApp', [])
.controller("myController", function ($scope, $http, $log) {
var successCallback = function (response) {
$scope.students = response.data;
$log.info(response);
}
var errorCallback = function (response) {
$scope.error = response.data;
$log.info(response);
}
$scope.StudentsData = $http({
method: 'GET',
url: 'PKWebService.asmx/getPkData'
})
.then(successCallback, errorCallback);
$scope.trimName = function (std) {
std.trimmed_name = std.Name.substring(0, 4);
return std;
};
});
and output is
Thank you

Categories