I want to transfer the value from three inputs: "name", "counter" and "price" to the array "products" that I then display in the table. But when I add them using the buttAdd.addEventListener handler, the new elements are not displayed in the table Help fix this
//Product Creation Class
class Product {
constructor(name, count, price) {
this.name = name;
this.count = count;
this.price = price;
}
}
// Сlass where products are recorded
class Shop {
constructor(products) {
this.products = [];
}
//method for adding a product
addProduct(newProduct) {
this.products.push(newProduct);
}
show() {
const rows = document.querySelectorAll("#shop .data");
for (let i = rows.length - 1; i >= 0; i--) {
const e = rows.item(i);
e.parentNode.removeChild(e);
}
const table = document.getElementById("shop");
for (let i = 0; i < this.products.length; i++) {
//create table
table.innerHTML += `<tr class="data"><td>${this.products[i].name}</td>
<td>${this.products[i].price}</td>
<td>${this.products[i].count}</td></tr>`;
}
}
}
const formAdd = document.forms[0];
const inputsAdd = formAdd.elements;
const buttAdd = formAdd.elements[3];
buttAdd.addEventListener('click', (e) => {
for (let i = 0; i <= 3; i++) {
shop.addProduct(inputsAdd[i].value);
}
shop.show();
}, false);
let shop = new Shop();
shop.addProduct(new Product("product 1", 1, 2000));
shop.show();
<form id="addForm">
<label for="name" >Name of product</label>
<input type="text" id="name" class="input-product">
<label for="price">Price of product</label>
<input type="text" id="price" class="input-product">
<label for="count">Count of product</label>
<input type="text" id="count" class="input-product">
<button id="add">Add</button>
</form>
<table id="shop">
<caption>Products that are available in the store</caption>
<tr>
<th>Name:</th>
<th id="filter">Price:</th>
<th>Count:</th>
</tr>
</table>
Below are the errors in your code.
Your for loop inside buttAdd.addEventListener is not correct.condition <=3 will iterate 4 time while input fields are only 3.
shop.addProduct(inputsAdd[i].value); is wrong because addProduct method of shop class required Product class object so you need to create new Product class object and set the values of input through constructor.
This is the correct way:
shop.addProduct(new Product(inputsAdd[0].value,inputsAdd[1].value,inputsAdd[2].value));
Here is the running snippet
//Product Creation Class
class Product {
constructor(name, count, price) {
this.name = name;
this.count = count;
this.price = price;
}
}
// Сlass where products are recorded
class Shop {
constructor(products) {
this.products = [];
}
//method for adding a product
addProduct(newProduct) {
this.products.push(newProduct);
}
show() {
const rows = document.querySelectorAll("#shop .data");
for (let i = rows.length - 1; i >= 0; i--) {
const e = rows.item(i);
e.parentNode.removeChild(e);
}
const table = document.getElementById("shop");
for (let i = 0; i < this.products.length; i++) {
//create table
table.innerHTML += `<tr class="data"><td>${this.products[i].name}</td>
<td>${this.products[i].price}</td>
<td>${this.products[i].count}</td></tr>`;
}
}
}
const formAdd = document.forms[0];
const inputsAdd = formAdd.elements;
const buttAdd = formAdd.elements[3];
//console.log(buttAdd);
buttAdd.addEventListener('click', (e) => {
e.preventDefault();
shop.addProduct(new Product(inputsAdd[0].value,parseInt(inputsAdd[1].value),inputsAdd[2].value));
shop.show();
}, false);
let shop = new Shop();
shop.addProduct(new Product("product 1", 1, 2000));
shop.show();
<form id="addForm">
<label for="name" >Name of product</label>
<input type="text" id="name" class="input-product">
<label for="price">Price of product</label>
<input type="text" id="price" class="input-product">
<label for="count">Count of product</label>
<input type="text" id="count" class="input-product">
<button id="add">Add</button>
</form>
<table id="shop">
<caption>Products that are available in the store</caption>
<tr>
<th>Name:</th>
<th id="filter">Price:</th>
<th>Count:</th>
</tr>
</table>
Your addProduct() method takes in a Product object as input, but in click listener you are passing form field input values without forming a object
//Product Creation Class
class Product {
constructor(name, count, price) {
this.name = name;
this.count = count;
this.price = price;
}
}
// Сlass where products are recorded
class Shop {
constructor(products) {
this.products = [];
}
//method for adding a product
addProduct(newProduct) {
this.products.push(newProduct);
}
show() {
const rows = document.querySelectorAll("#shop .data");
for (let i = rows.length - 1; i >= 0; i--) {
const e = rows.item(i);
e.parentNode.removeChild(e);
}
const table = document.getElementById("shop");
for (let i = 0; i < this.products.length; i++) {
//create table
table.innerHTML += `<tr class="data"><td>${this.products[i].name}</td>
<td>${this.products[i].price}</td>
<td>${this.products[i].count}</td></tr>`;
}
}
}
const formAdd = document.forms[0];
const inputsAdd = formAdd.elements;
const buttAdd = formAdd.elements[3];
buttAdd.addEventListener('click', (e) => {
e.preventDefault();
let tempProduct = new
Product(inputsAdd[0].value,parseInt(inputsAdd[1].value),parseInt(inputsAdd[2].value));
shop.addProduct(tempProduct);
shop.show();
}, false);
let shop = new Shop();
shop.addProduct(new Product("product 1", 1, 2000));
shop.show();
<form id="addForm">
<label for="name" >Name of product</label>
<input type="text" id="name" class="input-product">
<label for="price">Price of product</label>
<input type="text" id="price" class="input-product">
<label for="count">Count of product</label>
<input type="text" id="count" class="input-product">
<button id="add">Add</button>
</form>
<table id="shop">
<caption>Products that are available in the store</caption>
<tr>
<th>Name:</th>
<th id="filter">Price:</th>
<th>Count:</th>
</tr>
</table>
Related
function createPerson() {
var fullname = document.getElementById('inputValueFullname').value;
var age = document.getElementById('inputValueAge').value;
var amka = document.getElementById('inputValueAmka').value;
function person(fullname, age, amka) {
this.fullname = fullname;
this.age = age;
this.amka = amka;
}
var NewPerson = new person(name, age, amka);
console.log(NewPerson);
}
<label>Fullname: <input type="text" id="inputValueFullname"></label>
<label>Age:<input type="text" id="inputValueAge"></label>
<label>Amka:<input type="text" id="inputValueAmka"></label>
<button id="btn" onclick="createPerson();">Add</button>
I want someone to help me with 2 problems
the user gives full name age and amka and I want them all to appear below in a list as in the photo below
I have a code that I tried separately but I do not know how to put them together
i want when someone give age<18 to stop to take more inputs
to use for this for or if and how to do it
function publishToTable() {
const fullname = document.getElementById('fullname').value;
const age = document.getElementById('age').value;
const amka = document.getElementById('amka').value;
const error = document.getElementById('error');
if (fullname && age && amka) {
const tableElement = document.getElementById('table');
const trElement = document.createElement('tr');
const tbodyElement = document.createElement('tbody');
const fullnameEle = document.createElement('td');
const ageEle = document.createElement('td');
const amkaEle = document.createElement('td');
fullnameEle.innerHTML = fullname;
ageEle.innerHTML = age;
amkaEle.innerHTML = amka;
trElement.appendChild(fullnameEle);
trElement.appendChild(ageEle);
trElement.appendChild(amkaEle);
tbodyElement.appendChild(trElement);
tableElement.appendChild(tbodyElement);
}
}
<div class="complete">
<div class="form">
<label>Fullname: <input id="fullname" type="text"></label>
<label>Age: <input id="age" type="text"></label>
<label>AMKA: <input id="amka" type="text"></label>
<span id="error"></span>
<button onclick="publishToTable()">Submit</button>
</div>
<div id="tables">
<table id="table">
<thead>
<tr>
<th>Name/Surname</th>
<th>Age</th>
<th>AMKA</th><br><br><br><br><br>
</tr>
</thead>
</table>
</div>
</div>
I suggest you use an array.
I have made some other recommended changes, such as using an eventListener and an Array.map
const person = (fullname, age, amka) => ({ fullname, age, amka }); // return an object, shorthand for { "fullname": fullname ....
const persons = [];
const error = document.getElementById('error');
const tableElement = document.getElementById('table');
const fullnameField = document.getElementById('fullname')
const ageField = document.getElementById('age')
const amkaField = document.getElementById('amka')
const publishToTable = () => tableElement.innerHTML = persons
.map(({ fullname, age, amka }) => `<tr><td>${fullname}</td><td>${age}</td><td>${amka}</td></tr>`).join("");
document.getElementById("save").addEventListener("click", e => {
let fullname = fullnameField.value;
let age = +ageField.value; // cast to number
let amka = amkaField.value;
if (isNaN(age) || age < 18) {
ageField.focus();
error.innerHTML = "Incorrect age (18 minimum)"
return; // stop
}
error.innerHTML = "";
persons.push(person(fullname, age, amka));
fullnameField.value = ageField.value = amkaField.value = ""; // reset
fullnameField.focus()
publishToTable();
})
<div class="complete">
<div class="form">
<label>Fullname: <input id="fullname" type="text"></label>
<label>Age: <input id="age" type="text"></label>
<label>AMKA: <input id="amka" type="text"></label>
<span id="error"></span>
<button type="button" id="save">Save</button>
</div>
<div id="tables">
<table>
<thead>
<tr>
<th>Name/Surname</th>
<th>Age</th>
<th>AMKA</th><br><br><br><br><br>
</tr>
</thead>
<tbody id="table">
</table>
</table>
</div>
</div>
I want to total up one column in my table. My array list holds two objects and generates a table using a function from that array. My function to sum one specific column(the number of miles) isn't outputting anything to my webpage. I want on the click of Get Status, the total number of miles to display.
I tried the code mentioned by putting it in a separate function, but it didn't work.
<body>
<label>Please enter your flight Number:</label><br>
<input type="text" id="flightNumber" name="flightnumber" value="" /> <br />
<label>Please enter Miles Flown:</label><br>
<input type="text" id="milesFlown" name="milesflown" value="" />
<br>
<input type="button" id="display" name="display" value="Submit Flight Information" />
<br>
<div id ="classMessages"></div>
<input type="button" id="status" name="status" value="Get Class Status" onclick= getClassStatus(); />
<table id="flightTable">
<tr>
<th>Flight Number</th>
<th>Miles Flown</th>
</tr>
</table>
</div>
<script type="text/javascript">
const flightTable = document.getElementById('flightTable'),
button = document.getElementById('display'),
flightNum = document.getElementById('flightNumber'),
milesFlown = document.getElementById('milesFlown'),
addRow = () => {
const tr = document.createElement('tr'),
tdFlightNo = document.createElement('td'),
tdMilesFlown = document.createElement('td');
tdMilesFlown.setAttribute('class', 'needsToBeCounted');
/** getting the last record in the flight objects array **/
tdFlightNo.textContent = flightArray[i - 1].flightNumber;
tdMilesFlown.textContent = flightArray[i - 1].milesFlown;
/** append the TDs elements to the TR element (all of them are created above dynamically) **/
tr.append(tdFlightNo, tdMilesFlown);
/** append that row to the HTML table **/
flightTable.appendChild(tr);
}
let flightArray = [],
flightNumValue = null,
milesFlownValue = null,
i = 0;
button.addEventListener('click', () => {
flightNumValue = flightNum.value;
milesFlownValue = milesFlown.value;
/** checking for duplicate entry **/
if (flightArray.find(el => {
return el.flightNumber === flightNumValue
})) {
alert('You cannot enter this flight due to Duplicate Flight Number entry: "' + flightNumValue + '"');
return false;
}
/** add the entry in the flight objects table **/
flightArray[i++] = {
flightNumber: flightNumValue,
milesFlown: milesFlownValue
}; /** add the flight record to the array and increment the counter i (notice the i++) **/
addRow(); /** call addRow to add a new row in the table (HTML) **/
});
function getClassStatus(){
var cls = document.getElementById("flightTable").getElementsByTagName("td");
for (var i = 0; i < cls.length; i++){
if(cls[i].className == "needsToBeCounted"){
total += isNaN(cls[i].innerHTML) ? 0 : parseInt(cls[i].innerHTML);
}
console.log(total);
</script>
Uncaught ReferenceError: getClassStatus is not defined when clicking my button to total the miles.
There is only one issue with the code, total variable is not declared.
var total = 0;
const flightTable = document.getElementById('flightTable'),
button = document.getElementById('display'),
flightNum = document.getElementById('flightNumber'),
milesFlown = document.getElementById('milesFlown'),
addRow = () => {
const tr = document.createElement('tr'),
tdFlightNo = document.createElement('td'),
tdMilesFlown = document.createElement('td');
tdMilesFlown.setAttribute('class', 'needsToBeCounted');
/** getting the last record in the flight objects array **/
tdFlightNo.textContent = flightArray[i - 1].flightNumber;
tdMilesFlown.textContent = flightArray[i - 1].milesFlown;
/** append the TDs elements to the TR element (all of them are created above dynamically) **/
tr.append(tdFlightNo, tdMilesFlown);
/** append that row to the HTML table **/
flightTable.appendChild(tr);
}
let flightArray = [],
flightNumValue = null,
milesFlownValue = null,
i = 0;
button.addEventListener('click', () => {
flightNumValue = flightNum.value;
milesFlownValue = milesFlown.value;
/** checking for duplicate entry **/
if (flightArray.find(el => {
return el.flightNumber === flightNumValue
})) {
alert('You cannot enter this flight due to Duplicate Flight Number entry: "' + flightNumValue + '"');
return false;
}
/** add the entry in the flight objects table **/
flightArray[i++] = {
flightNumber: flightNumValue,
milesFlown: milesFlownValue
}; /** add the flight record to the array and increment the counter i (notice the i++) **/
addRow(); /** call addRow to add a new row in the table (HTML) **/
});
function getClassStatus() {
var cls = document.getElementById("flightTable").getElementsByTagName("td");
for (var i = 0; i < cls.length; i++) {
if (cls[i].className == "needsToBeCounted") {
total += isNaN(cls[i].innerHTML) ? 0 : parseInt(cls[i].innerHTML);
}
}
console.log(total);
}
<label>Please enter your flight Number:</label><br>
<input type="text" id="flightNumber" name="flightnumber" value="" /> <br />
<label>Please enter Miles Flown:</label><br>
<input type="text" id="milesFlown" name="milesflown" value="" />
<br>
<input type="button" id="display" name="display" value="Submit Flight Information" />
<br>
<div id="classMessages"></div>
<input type="button" id="status" name="status" value="Get Class Status" onclick=getClassStatus(); />
<table id="flightTable">
<tr>
<th>Flight Number</th>
<th>Miles Flown</th>
</tr>
</table>
</div>
When the listener "buttAdd.addEventListener" for the add method is triggered: , first this condition works several times(works with the second addition):
if (inputsAdd [0].value ===""||inputsAdd [1].value ===""||inputsAdd [2]
.value === "")
{alert ("fill all fields");}
It works when the fields are not empty, and then the product is added. And if you click on the add button with empty fields, then the product that was added earlier - will be lost. The same story awith the method, delete. Help me please to fix it
//Product Creation Class
class Product {
constructor(name, count, price) {
this.name = name;
this.count = count;
this.price = price;
}
}
Product.SORT_ORDER_ASC = 1;
Product.SORT_ORDER_DESC = -1;
// Сlass where products are recorded
class Shop {
constructor() {
this.products = [];
this.formAdd = document.forms[0];
this.inputsAdd = this.formAdd.elements;
this.buttAdd = this.formAdd.elements[3];
this.formDelete = document.forms[1];
this.nameDelete = this.formDelete.elements[0];
this.buttDelete = this.formDelete.elements[1];
}
//method for adding a product
addProduct(newProduct) {
this.products.push(newProduct);
}
//method for remove product by name
deleteProductByName(productName) {
let i = this.products.length;
while (i--) {
if (productName === this.products[i].name) {
this.products.splice(i, 1);
}
}
}
// get total price by all products
get totalProductsPrice() {
return this.products.map(product => product.price).reduce((p, c) => p + c);
}
//method for sorting the product at its price
sortProductsByPrice(sortOrder) {
const sorted = this.products.sort((a, b) => {
return a.price > b.price ? sortOrder : -sortOrder;
});
this.products = sorted;
}
// method to draw the table with product property (
// name, count, price)
show() {
// add new product by click
this.buttAdd.addEventListener('click', (e) => {
e.preventDefault();
if (this.inputsAdd[0].value === "" || this.inputsAdd[1].value === "" || this.inputsAdd[2].value === "") {
alert("fill all fields");
} else {
this.addProduct(new Product(this.inputsAdd[0].value, parseInt(this.inputsAdd[2].value),
parseInt(this.inputsAdd[1].value)));
this.show();
this.inputsAdd[0].value = "";
this.inputsAdd[1].value = "";
this.inputsAdd[2].value = "";
}
}, false);
// delete product by name after click
this.buttDelete.addEventListener('click', (e) => {
e.preventDefault();
if (this.nameDelete.value === "") {
alert("write a name of product what you want to delete");
} else {
this.deleteProductByName(this.nameDelete.value);
this.show();
this.nameDelete.value = "";
}
}, false);
const rows = document.querySelectorAll("#shop .data");
for (let i = rows.length - 1; i >= 0; i--) {
const e = rows.item(i);
e.parentNode.removeChild(e);
}
const table = document.getElementById("shop");
const tFoot = table.querySelector('tfoot');
if (tFoot) tFoot.remove();
for (let i = 0; i < this.products.length; i++) {
//create table
table.innerHTML += `<tbody><tr class="data"><td>${this.products[i].name}</td>
<td>${this.products[i].price}</td>
<td>${this.products[i].count}</td></tr></tbody>`;
}
//show total price by all products
table.innerHTML += `<tfoot><tr><td colspan="3" id="total-price">Total price:
${this.totalProductsPrice}</td></tr></tfoot>`;
//filter products by price
document.addEventListener("click", (e) => {
let elem = e.target;
if (elem.id === "filter") {
this.sortProductsByPrice(Product.SORT_ORDER_ASC);
this.show();
}
}, false);
console.log(this.products);
}
}
let shop = new Shop();
shop.addProduct(new Product("product", 1, 2000));
shop.addProduct(new Product("product1", 2, 500));
shop.addProduct(new Product("product2", 3, 1000));
shop.show();
<div class="Shop">
<div class="add-product">
<h1>Add product</h1>
<form id="addForm">
<label for="name" >Name of product</label>
<input type="text" id="name" class="input-product">
<label for="price">Price of product</label>
<input type="text" id="price" class="input-product">
<label for="count">Count of product</label>
<input type="text" id="count" class="input-product">
<button id="add" type="button">Add</button><!-- *** -->
</form>
</div>
<div class="product-table">
<h2>Products</h2>
<form id="delete-form">
<label for="name-delete">Delete product by name</label>
<input type="text" id="name-delete" class="input-delete">
<button id="delete" type="button">Delete</button>
</form>
<table id="shop">
<caption>Products that are available in the store</caption>
<tr>
<th>Name:</th>
<th id="filter">Price:</th>
<th>Count:</th>
</tr>
</table>
</div>
</div>
See, you're defining let shop = new Shop() and then use this variable in your Shop class, like shop.show(). I strongly recommend you to use this keyword instead of scoped variable (valid for all other shop usage entries).
Now, about
works several times
I assume, that when you call the show() method it registers more event listeners some time. I mean, you call show - it creates new event listeners + sometimes calls itself (huh, it is pretty risky). I suggest you to move listeners declaration to the constructor - so they will be instantinated once (but that will require keeping DOM nodes). Also it would be nice to split your show fucntion to several smaller functions and get rid of self function emit (it will reduce complexity).
In the sortProductsByPrice (sortOrder) method, sorting does not work when I delete or add new products, sorting works only for products that are in the this.products array by default.
(Products are sorted by clicking <th> Price: </ th>).
It is necessary that sorting can use too after removal / addition of goods.
//Product Creation Class
class Product {
constructor(name, count, price) {
this.name = name;
this.count = count;
this.price = price;
}
}
Product.SORT_ORDER_ASC = 1;
Product.SORT_ORDER_DESC = -1;
// Сlass where products are recorded
class Shop {
constructor() {
this.products = [];
}
//method for adding a product
addProduct(newProduct) {
this.products.push(newProduct);
}
//method for remove product by name
deleteProductByName(productName) {
let i = this.products.length;
while (i--) {
if (productName === this.products[i].name) {
this.products.splice(i, 1);
}
}
}
// get total price by all products
get totalProductsPrice() {
return this.products.map(product => product.price).reduce((p, c) => p + c);
}
//method for sorting the product at its price
sortProductsByPrice(sortOrder) {
const sorted = this.products.sort((a, b) => {
return a.price > b.price ? sortOrder : -sortOrder;
});
this.products = sorted;
}
// method to draw the table with product property (
// name, count, price)
show() {
const formAdd = document.forms[0];
const inputsAdd = formAdd.elements;
const buttAdd = formAdd.elements[3];
const formDelete = document.forms[1];
const nameDelete = formDelete.elements[0];
const buttDelete = formDelete.elements[1];
const priceFilter = document.getElementById("filter");
// add new product by click
buttAdd.addEventListener('click', (e) => {
e.preventDefault();
shop.addProduct(new Product(inputsAdd[0].value, parseInt(inputsAdd[2].value),
parseInt(inputsAdd[1].value)));
shop.show();
}, false);
// delete product by name after click
buttDelete.addEventListener('click', (e) => {
e.preventDefault();
shop.deleteProductByName(nameDelete.value);
shop.show();
}, false);
const rows = document.querySelectorAll("#shop .data");
for (let i = rows.length - 1; i >= 0; i--) {
const e = rows.item(i);
e.parentNode.removeChild(e);
}
const table = document.getElementById("shop");
const tFoot = table.querySelector('tfoot');
if (tFoot) tFoot.remove();
for (let i = 0; i < this.products.length; i++) {
//create table
table.innerHTML += `<tbody><tr class="data"><td>${this.products[i].name}</td>
<td>${this.products[i].price}</td>
<td>${this.products[i].count}</td></tr></tbody>`;
}
//show total price by all products
table.innerHTML += `<tfoot><tr><td colspan="3" id="total-price">Total price:
${shop.totalProductsPrice}</td></tr></tfoot>`;
priceFilter.addEventListener("click", (e) => {
shop.sortProductsByPrice(Product.SORT_ORDER_ASC);
shop.show();
}, false);
}
}
let shop = new Shop();
shop.addProduct(new Product("product", 1, 2000));
shop.addProduct(new Product("product1", 2, 500));
shop.addProduct(new Product("product2", 3, 1000));
shop.show();
console.log(shop.products);
<div class="Shop">
<div class="add-product">
<h1>Add product</h1>
<form id="addForm">
<label for="name" >Name of product</label>
<input type="text" id="name" class="input-product">
<label for="price">Price of product</label>
<input type="text" id="price" class="input-product">
<label for="count">Count of product</label>
<input type="text" id="count" class="input-product">
<button id="add">Add</button>
</form>
</div>
<div class="product-table">
<h2>Products</h2>
<form id="delete-form">
<label for="name-delete">Delete product by name</label>
<input type="text" id="name-delete" class="input-delete">
<button id="delete" type="button">Delete</button>
</form>
<table id="shop">
<caption>Products that are available in the store</caption>
<tr>
<th>Name:</th>
<th id="filter">Price:</th>
<th>Count:</th>
</tr>
</table>
</div>
</div>
It is necessary that sorting can use too after removal / addition of goods
The sorting is not working after addition/removal because you are calling show() method after adding/removing element, which will redraw the whole HTML, without attaching any events to it, so the originally attached event handlers will be unbound.
You need to attach the event handlers in your show() method to resolve this problem.
And there's no need to return the sorted array in your method, the original this.products will be sorted in place.
So there's no need to declare sorted array, and return it, just write the this.products.sort() code it will sort the array.
sortProductsByPrice(sortOrder) {
this.products.sort((a, b) => {
return a.price > b.price ? sortOrder : -sortOrder;
});
}
Demo:
//Product Creation Class
class Product {
constructor(name, count, price) {
this.name = name;
this.count = count;
this.price = price;
}
}
Product.SORT_ORDER_ASC = 1;
Product.SORT_ORDER_DESC = -1;
// Сlass where products are recorded
class Shop {
constructor() {
this.products = [];
}
//method for adding a product
addProduct(newProduct) {
this.products.push(newProduct);
}
//method for remove product by name
deleteProductByName(productName) {
let i = this.products.length;
while (i--) {
if (productName === this.products[i].name) {
this.products.splice(i, 1);
}
}
}
// get total price by all products
get totalProductsPrice() {
return this.products.map(product => product.price).reduce((p, c) => p + c);
}
//method for sorting the product at its price
sortProductsByPrice(sortOrder) {
this.products.sort((a, b) => {
return a.price > b.price ? sortOrder : -sortOrder;
});
}
// method to draw the table with product property (
// name, count, price)
show() {
const rows = document.querySelectorAll("#shop .data");
for (let i = rows.length - 1; i >= 0; i--) {
const e = rows.item(i);
e.parentNode.removeChild(e);
}
const table = document.getElementById("shop");
const tFoot = table.querySelector('tfoot');
if (tFoot) tFoot.remove();
for (let i = 0; i < this.products.length; i++) {
//create table
table.innerHTML += `<tbody><tr class="data"><td>${this.products[i].name}</td>
<td>${this.products[i].price}</td>
<td>${this.products[i].count}</td></tr></tbody>`;
}
//show total price by all products
table.innerHTML += `<tfoot><tr><td colspan="3" id="total-price">Total price:
${shop.totalProductsPrice}</td></tr></tfoot>`;
}
}
// add new product by click
const formAdd = document.forms[0];
const inputsAdd = formAdd.elements;
const buttAdd = formAdd.elements[3];
buttAdd.addEventListener('click', (e) => {
e.preventDefault();
shop.addProduct(new Product(inputsAdd[0].value, parseInt(inputsAdd[2].value),
parseInt(inputsAdd[1].value)));
shop.show();
}, false);
// delete product by name after click
const formDelete = document.forms[1];
const nameDelete = formDelete.elements[0];
const buttDelete = formDelete.elements[1];
buttDelete.addEventListener('click', (e) => {
e.preventDefault();
shop.deleteProductByName(nameDelete.value);
shop.show();
}, false);
let shop = new Shop();
shop.addProduct(new Product("product", 1, 2000));
shop.addProduct(new Product("product1", 2, 500));
shop.addProduct(new Product("product2", 3, 1000));
shop.show();
const priceFilter = document.getElementById("filter");
//filter products by price
priceFilter.addEventListener("click", (e) => {
shop.sortProductsByPrice(Product.SORT_ORDER_ASC);
shop.show();
}, false);
<div class="Shop">
<div class="add-product">
<h1>Add product</h1>
<form id="addForm">
<label for="name">Name of product</label>
<input type="text" id="name" class="input-product">
<label for="price">Price of product</label>
<input type="text" id="price" class="input-product">
<label for="count">Count of product</label>
<input type="text" id="count" class="input-product">
<button id="add">Add</button>
</form>
</div>
<div class="product-table">
<h2>Products</h2>
<form id="delete-form">
<label for="name-delete">Delete product by name</label>
<input type="text" id="name-delete" class="input-delete">
<button id="delete" type="button">Delete</button>
</form>
<table id="shop">
<caption>Products that are available in the store</caption>
<tr>
<th>Name:</th>
<th id="filter">Price:</th>
<th>Count:</th>
</tr>
</table>
</div>
</div>
The method of removing products by their name does not work. I'm trying to delete using buttDelete.addEventListener but the deletion does not happen.
The logic of the deleteProductByName method is that when the name of product is received from input nameDelete it is checked the same products in shop.products array, then when the button delete is press (buttDelete), the product is deleted from the array and correspondingly from the table too, if the field is empty, then output alert that you need to fill out the field.
Help please fix that
//Product Creation Class
class Product {
constructor(name, count, price) {
this.name = name;
this.count = count;
this.price = price;
}
}
// Сlass where products are recorded
class Shop {
constructor() {
this.products = [];
}
//method for adding a product
addProduct(newProduct) {
this.products.push(newProduct);
}
//method for remove product by name
deleteProductByName(productName) {
let i = this.products.length;
while (i--) {
if (productName === this.products[i].name) {
this.products.splice(i, 1);
}
}
}
// get total price by all products
get totalProductsPrice() {
return this.products.map(product => product.price).reduce((p, c) => p + c);
}
// method to draw the table with product property (
// name, count, price)
show() {
const rows = document.querySelectorAll("#shop .data");
for (let i = rows.length - 1; i >= 0; i--) {
const e = rows.item(i);
e.parentNode.removeChild(e);
}
const table = document.getElementById("shop");
for (let i = 0; i < this.products.length; i++) {
//create table
table.innerHTML += `<tbody><tr class="data"><td>${this.products[i].name}</td>
<td>${this.products[i].price}</td>
<td>${this.products[i].count}</td></tr></tbody>`;
}
//show total price by all products
table.innerHTML += `<tfoot><tr id="total-price"><td colspan="3">Total price:
${shop.totalProductsPrice}</td></tr></tfoot>`;
}
}
// add new product by click
const formAdd = document.forms[0];
const inputsAdd = formAdd.elements;
const buttAdd = formAdd.elements[3];
buttAdd.addEventListener('click', (e) => {
e.preventDefault();
shop.addProduct(new Product(inputsAdd[0].value, parseInt(inputsAdd[2].value),
parseInt(inputsAdd[1].value)));
shop.show();
}, false);
// delete product by name after click
const formDelete = document.forms[1];
const nameDelete = formDelete.elements[0];
const buttDelete = formDelete.elements[1];
buttDelete.addEventListener('click', (e) => {
e.preventDefault();
shop.deleteProductByName(nameDelete.value);
shop.show();
}, false);
let shop = new Shop();
shop.addProduct(new Product("product 1", 1, 2000));
shop.show();
<div class="Shop">
<div class="add-product">
<h1>Add product</h1>
<form id="addForm">
<label for="name" >Name of product</label>
<input type="text" id="name" class="input-product">
<label for="price">Price of product</label>
<input type="text" id="price" class="input-product">
<label for="count">Count of product</label>
<input type="text" id="count" class="input-product">
<button id="add">Add</button>
</form>
</div>
<div class="product-table">
<h2>Products</h2>
<form id="delete-form">
<label for="name-delete">Delete product by name</label>
<input type="text" id="name-delete" class="input-delete">
<button id="delete" type="button">Delete</button>
</form>
<table id="shop">
<caption>Products that are available in the store</caption>
<tr>
<th>Name:</th>
<th id="filter">Price:</th>
<th>Count:</th>
</tr>
</table>
</div>
</div>
Then I would use a console.log() or a debugger on
//method for remove product by name
deleteProductByName(productName) {
let i = this.products.length;
while (i--) {
console.log("productName " + productName + "this.products[i].name" + this.products[i].name);
if (productName === this.products[i].name) {
this.products.splice(i, 1);
}
}
}
to see if you comparing the same names. To make sure your if statement is working as expected.