英文:
Novice coder question - JS User-generated shopping list - How to update number property of list objects and avoid duplicates
问题
以下是您要翻译的代码部分:
e.g. if a user submits "tacos" twice, instead of having two lines, each containing "tacos", I want to have one line with "tacos x 2". Question 2 - is it possible to create a variable that selects every item in an array except another variable? e.g.
for (let i = 0; i < items.length; i++) {
let j = !i;
}
(I am aware the above code is incorrect, I included it only to illustrate my question)
Thank you in advance.
// key function out of context
if (!items.includes(item.text)) {
items.push(item);
} else {
items.item.number =+1
}
如果您有其他问题或需要进一步的帮助,请随时告诉我。
英文:
e.g. if a user submits "tacos" twice, instead of having two lines, each containing "tacos", I want to have one line with "tacos x 2". Question 2 - is it possible to create a variable that selects every item in an array except another variable? e.g.
for (let i = 0; i < items.length; i++)
{let j = !i;
}
(I am aware the above code is incorrect, I included it only to illustrate my question)
Thank you in advance.
// key function out of context
if (!items.includes(item.text)) {
items.push(item);
} else {
items.item.number =+1
}
//entire html file with script including key function in context
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>LocalStorage</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="wrapper">
<h2>LOCAL TAPAS</h2>
<p></p>
<ul class="plates">
<li>Loading Tapas...</li>
</ul>
<form class="add-items" autocomplete="off">
<input type="text" name="item" placeholder="Item Name" required>
<input type="submit" value="+ Add Item">
</form>
<button type="reset" value="reset"">clear all</button>
<button class="select">Select all</button>
</div>
<script>
const addItems = document.querySelector('.add-items');
const itemsList = document.querySelector('.plates');
const selectAll = document.querySelector('.select');
const items = [];
const mySet = new Set();
const userInput = document.querySelector('[type="text"]');
// add items to list
// populate list with html
function add(e) {
e.preventDefault();
console.dir(e.currentTarget)
const text = e.currentTarget.item.value;
const item = {
text,
done:false,
number: 1,
};
console.dir(item)
if (!items.includes(item.text)) {
items.push(item);
} else {
items.item.number =+1
}
e.currentTarget.reset();
itemsList.dispatchEvent(new CustomEvent('itemsUpdated'))
}
function displayItems(item, i) {
const html = items.map((item, i) => `
<li>
<input type="checkbox">
<label name="${item}" id="${i}"><strong>${item.text}</strong> x${item.number} </label>
</li>`).join('');
itemsList.innerHTML = html;
};
addItems.addEventListener('submit', add)
itemsList.addEventListener('itemsUpdated', displayItems)
</script>
</body>
</html>
答案1
得分: 0
问题出在于您如何检查item
对象是否在items
数组中。
由于数组的元素是对象,您需要修改检查的方式 - includes
和indexOf
都不起作用。
您需要这样做:
let indx = items.findIndex(element => element.text === item.text);
array.findIndex
允许您在数组中找到满足给定条件的元素。在这种情况下,您想根据名称查找特定产品。这就是为什么我们要执行element.text === item.text
比较。
查看下面的更新示例,以查看它的运行方式。
<!-- begin snippet: js hide: false console: false babel: false -->
<!-- language: lang-js -->
const addItems = document.querySelector('.add-items');
const itemsList = document.querySelector('.plates');
const selectAll = document.querySelector('.select');
const items = [];
const mySet = new Set();
const userInput = document.querySelector('[type="text"]');
// add items to list
// populate list with html
function add(e) {
e.preventDefault();
const text = e.currentTarget.item.value;
const item = {
text,
done:false,
number: 1,
};
/* 这些是关键更改 */
let indx = items.findIndex(element => element.text === item.text);
if (indx < 0) {
items.push(item);
} else {
items[indx].number += 1;
}
/* */
e.currentTarget.reset();
itemsList.dispatchEvent(new CustomEvent('itemsUpdated'))
}
function displayItems(item, i) {
const html = items.map((item, i) => `
<li>
<input type="checkbox">
<label name="${item}" id="${i}"><strong>${item.text}</strong> x${item.number}</label>
</li>
`).join('');
itemsList.innerHTML = html;
};
addItems.addEventListener('submit', add)
itemsList.addEventListener('itemsUpdated', displayItems)
<!-- language: lang-html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>LocalStorage</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="wrapper">
<h2>LOCAL TAPAS</h2>
<p></p>
<ul class="plates">
<li>Loading Tapas...</li>
</ul>
<form class="add-items" autocomplete="off">
<input type="text" name="item" placeholder="Item Name" required>
<input type="submit" value="+ Add Item">
</form>
<button type="reset" value="reset">clear all</button>
<button class="select">Select all</button>
</div>
</body>
</html>
<!-- end snippet -->
**编辑** 还有一些小的语法错误更正:
- 在您的原始代码中,重置按钮的值是`value="reset"'"。我已经删除了额外的引号。
- 您对`item.number`的初始递增也是错误的 - 与`items.item.number =+1`不同,它应该是(如现在的那样)`items[indx].number += 1`。请注意是`+=`而不是`=+`。
<details>
<summary>英文:</summary>
The problem lies with how you're checking if your `item` object is in the `items` array.
Since the elements of your array are objects, you would need to modify that checkup - `includes` and `indexOf` won't work.
What you would need to do is:
let indx = items.findIndex(element => element.text === item.text);
[`array.findIndex`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex) will let you find an element within an array which satisfies the given condition. In this case, you want to find a specific product by name. That's why we're doing the `element.text === item.text` comparison.
Check the updated example below, to see it in action.
<!-- begin snippet: js hide: false console: false babel: false -->
<!-- language: lang-js -->
const addItems = document.querySelector('.add-items');
const itemsList = document.querySelector('.plates');
const selectAll = document.querySelector('.select');
const items = [];
const mySet = new Set();
const userInput = document.querySelector('[type="text"]');
// add items to list
// populate list with html
function add(e) {
e.preventDefault();
const text = e.currentTarget.item.value;
const item = {
text,
done:false,
number: 1,
};
/* these are the key changes */
let indx = items.findIndex(element => element.text === item.text);
if (indx < 0) {
items.push(item);
} else {
items[indx].number += 1;
}
/* */
e.currentTarget.reset();
itemsList.dispatchEvent(new CustomEvent('itemsUpdated'))
}
function displayItems(item, i) {
const html = items.map((item, i) => `
<li>
<input type="checkbox">
<label name="${item}" id="${i}"><strong>${item.text}</strong> x${item.number}</label>
</li>
`).join('');
itemsList.innerHTML = html;
};
addItems.addEventListener('submit', add)
itemsList.addEventListener('itemsUpdated', displayItems)
<!-- language: lang-html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>LocalStorage</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="wrapper">
<h2>LOCAL TAPAS</h2>
<p></p>
<ul class="plates">
<li>Loading Tapas...</li>
</ul>
<form class="add-items" autocomplete="off">
<input type="text" name="item" placeholder="Item Name" required>
<input type="submit" value="+ Add Item">
</form>
<button type="reset" value="reset">clear all</button>
<button class="select">Select all</button>
</div>
</body>
</html>
<!-- end snippet -->
**EDIT** There were also minor syntax error edits:
- in your original code, your reset button had this as its value - `value="reset""`. I've removed the extra quote.
- your initial incrementing of `item.number` was also erroneous - instead of `items.item.number =+1` it should have been (as it is now) `items[indx].number += 1`. Note that it's `+=` and not `=+`.
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论