javascript - 动态生成 HTML
问题描述
我是一个绝对的初学者,已经自学了两周,为一个月后的训练营做准备。为了提高我的技能并“学会像开发人员一样思考”,我承担了一个试图解决现实世界问题的项目。
我的妻子经营一家企业,要求她为客户开具发票。我正在尝试使用 HTML 和 JavaScript 来构建一个基于 Web 的应用程序,这使她能够快速创建自定义发票,而不是每次都手动将它们写出来。
在当前版本中,提示要求她提供一个号码。此数字在 HTML 中生成相同数量的三列行。这使她能够使用她需要的确切字段数自定义发票。
第 1 列包含产品名称。在同一行中,第 2 列包含单位数量,而第 3 列包含该产品的总成本,即基本价格乘以单位数量。我希望在单击按钮时进行此计算。但是,我被困住了。
为了执行数学运算,我需要能够从每一行和每一列中获取整数并将它们传递给一个函数。但是因为每一行和每一列都是自动生成的,它们没有唯一的属性,因此无法识别。我能够在每一列中执行数学运算,但不能在每一行中执行。
由于我是新手,只从几个介绍性 Codecademy 课程和一些 YouTube 视频中学习,我不知道如何评估我是否完全错误地接近该项目,或者我是否缺少一些技巧,或者如果还有一些东西还没有学到。如果有一些专业知识的人可以将我推向正确的方向,我将不胜感激!
我已将所有代码附加到这篇文章中。抱歉,如果这是一个可怕的混乱。放轻松,我是初学者!
const invDate = Date();
var field = "<label for='Item'>Item:</label> <input type=text name='item'>" +
"<label for='qty'> Qty: </label> <input type='number' name='qty'>" +
"<label for='Price'> Price ($):</label> <input type='number' name='price'> <br><br>";
document.getElementById('newInvoice').onclick = function(){
let invoicedName = prompt('Who is this invoice made out to?', 'Enter a name');
let productFields = Number(prompt('How many product names on this invoice?', 'Please enter a number'));
let fields = ''
let dynHtml = ''
if (invoicedName != null && productFields != null) {
for (let i = 1; i <= productFields; i++) {
fields += field };
} else { alert('Please enter valid inputs.');
};
dynHtml = "<center><img src ='logo.jpg'><br></br>" +
"<h1>INVOICE</h1>" +
"<p>Prepared for: <b>" + invoicedName + "</b>, on" +
"<p>" + invDate + "</p><br></br>" +
fields + "<br></br>" +
"<button id ='calculate'>Calculate</button></center>";
document.write(dynHtml);
document.getElementById('calculate').onclick = function getQtyFields() {
let qtyInputs = document.getElementsByName('qty'),
resultQty = 0;
for ( let j = 0; j < qtyInputs.length; j++ ) {
if ( qtyInputs[j].id.indexOf('qty') == 0 ) {
let num = parseFloat( qtyInputs[j].value );
if( !isNaN(num) ) resultQty += num;
}
}
let priceInputs = document.getElementsByName('price'),
resultPrice = 0;
for( let k = 0; k < priceInputs.length; k++ ) {
if( priceInputs[k].id.indexOf('price') == 0 ) {
let num = parseFloat( priceInputs[k].value );
if( !isNaN(num) ) resultPrice += num;
}
}
alert(resultQty); alert(resultPrice)
}
}
这是截图,
解决方案
正如您所说,您的主要问题是找到一种方法,让他们自己的行中的每个输入字段都有自己的唯一标识符。这样,您可以计算每行的价格并将其插入价格字段。
您首先必须从以下字段开始:
var field = "<label for='Item'>Item:</label> <input type=text name='item'>" +
"<label for='qty'> Qty: </label> <input type='number' name='qty'>" +
"<label for='Price'> Price ($):</label> <input type='number' name='price'> <br><br>";
document.getElementById('newInvoice').onclick = function(){
...
for (let i = 1; i <= productFields; i++) {
fields += field };
...
};
每个组都需要自己的标识符。这样,您以后可以参考每行中的每个输入来计算子总价。该class
属性是您可以分配给多个元素以便以后引用它们的东西。这class
可以是任何东西,只要它不与class
任何其他行的 相冲突。您可以使用i
循环的作为您的标识符,因为它随着每个循环而变化。
for (let i = 1; i <= productFields; i++) {
var field = "<label for='Item'>Item:</label> <input class='row-" + i + "' type=text name='item'>" +
"<label for='qty'> Qty: </label> <input class='row-" + i + "' type='number' name='qty'>" +
"<label for='Price'> Price ($):</label> <input class='row-" + i + "' type='number' name='price'> <br><br>";
fields += field
};
这会将类添加row-{i}
到每一行中的每个字段。更好的是,您可以将其重构为自己的函数
function generateFields(i) {
return "<label for='Item'>Item:</label> <input class='row-" + i + "' type=text name='item'>" +
"<label for='qty'> Qty: </label> <input class='row-" + i + "' type='number' name='qty'>" +
"<label for='Price'> Price ($):</label> <input class='row-" + i + "' type='number' name='price'> <br><br>";
}
for (let i = 1; i <= productFields; i++) {
fields += generateFields(i);
};
您会得到类似于以下 html 的内容
<label for='Item'>Item:</label> <input type=text class='row-1' name='item'>
<label for='qty'> Qty: </label> <input type='number' class='row-1' name='qty'>
<label for='Price'> Price ($):</label> <input type='number' class='row-1' name='price'> <br><br>
<label for='Item'>Item:</label> <input type=text class='row-2' name='item'>
<label for='qty'> Qty: </label> <input type='number' class='row-2' name='qty'>
<label for='Price'> Price ($):</label> <input type='number' class='row-2' name='price'> <br><br>
<label for='Item'>Item:</label> <input type=text class='row-3' name='item'>
<label for='qty'> Qty: </label> <input type='number' class='row-3' name='qty'>
<label for='Price'> Price ($):</label> <input type='number' class='row-3' name='price'> <br><br>
现在在您的计算函数中,您可以参考这些行并计算它们的价格。在这里,您可以遍历“项目”输入字段。
document.getElementById('calculate').onclick = function getQtyFields() {
let itemInputs= document.getElementsByName('item')
for(let i = 0; i < itemInputs.length; i++){
const identifier = itemInputs[i].className // get the class name of every item ex. 'row-1'
const row = document.getElementsByClassName(identifier);
}
...
}
row
现在是每行HTMLCollection
包含item
, qty
, 和price
的一个。您可以使用HTMLCollections
其名称选择其任何元素.namedItem(<name>)
for(let i = 0; i < itemInputs.length; i++){
const identifier = itemInputs[i].className // get the class name of every item ex. 'row-1'
const row = document.getElementsByClassName(identifier); // ex. 'row-1'
const qty = row.namedItem('qty').value;
const basePrice = [YOUR BASE PRICE];
const itemSubTotal = basePrice * qty; // heres is your item sub total!
}
您现在可以将价格price
插入该行的输入字段。
for(let i = 0; i < itemInputs.length; i++){
const identifier = itemInputs[i].className // get the class name of every item ex. 'row-1'
const row = document.getElementsByClassName(identifier); // ex. 'row-1'
const qty = row.namedItem('qty').value;
const basePrice = [YOUR BASE PRICE];
const itemSubTotal = basePrice * qty; // heres is your item sub total!
const price = row.namedItem('price');
price.value = itemSubTotal; // insert subtotal inside the price field
}
现在,一旦您单击计算,您应该会看到总价和总数量的警报,并且应该会看到price
填充了计算价格的输入字段。
这个解决方案非常基础,不应该引入任何你不知道的新概念。稍后在您的训练营中,您将了解可以使此类项目更易于管理和扩展的设计模式和框架。
如果遇到任何问题或有任何其他问题,请联系我!
推荐阅读
- android - 如何将第三方 iOS pod 库添加到 kotlin 原生项目中?收到错误“SharedCode:cinteropAFNetworkingIos 失败”
- flutter - 未处理的异常:RangeError(索引):索引超出范围:索引应小于
- graphql - 有什么方法可以编写 GraphQL 查询来获取 Shopify 产品评论
- angular - 如何传递请求模型以获取 Angular 7/8 上的 API?
- log4j - Appcenter Appium 测试 - java.io.FileNotFoundException(没有这样的文件或目录)
- c - C 中的 Downheap 实现
- sql - Conditionally perform SQL statements in a raw postgresql function?
- python - 使用 subprocess.Popen 打开 Terminal.app 会破坏 macOS 中的 conda
- python - 我尝试使用 pip install pyinstaller 安装 pyinstaller 并得到了这个:
- c++ - boost::beast - 自动重新连接 (Websocket, c++)