【问题标题】:Increment and update value in the total number after insert new rows dynamically动态插入新行后总数的增量和更新值
【发布时间】:2021-02-18 18:38:55
【问题描述】:

编辑:我已经用答案更新了代码。

我有一个工作正常的增量函数。然而:

1.我想根据其中一个跨度中可用的总数设置一些限制。比如10。所以增量不能超过10。#DONE

  1. 另一个问题是我计划有多个行,在我保存之前,我想确保我们是否计算每行的增量,它也不应该超过 10。如果它动态减少总数(跨度)会很好。

我正在使用 ADD 按钮动态添加行,如何添加实际与当前功能一起使用的新闻行?我的行只是克隆第一个行,增量功能被禁用。

document.addEventListener('DOMContentLoaded', async function() {
  document.querySelector('#addlocationdest').addEventListener('click', add);
});
function add() {
    var x = 1;
    var container = document.getElementById('destination');
    var detail = document.getElementById('row');
    var clone = detail.cloneNode(true);
    clone.id = "destination" + x;
    x++;
    container.appendChild(clone);

}

window.addEventListener("load", () => {
  let elTotalQuantity = document.querySelector("#totalqty");
  let totalQuantity = parseInt(elTotalQuantity.innerHTML);
  
  function getSumOfRows() {
    let sum = 0;
    for (let input of document.querySelectorAll("form .row > input.quantity"))
      sum += parseInt(input.value);
    return sum;
  }
  
  for (let row of document.querySelectorAll("form .row")) {
    let input = row.querySelector("input");
    row.querySelector(".increment").addEventListener("click", () => {
      if (getSumOfRows() >= totalQuantity) return;
      input.value++;
      elTotalQuantity.innerHTML = totalQuantity - getSumOfRows();
    });
    row.querySelector(".decrement").addEventListener("click", () => {
      if (input.value <= 0) return;
      input.value--;
      elTotalQuantity.innerHTML = totalQuantity - getSumOfRows();
    });
  }
});
<div id="location" class="hide">
                    <div class="title">Transfer details</div><br>
                    <div class="line padded-s">Total Quantity: <span>10</span></div>
                    <br>
                        <form>
                            <label>New Total Quantity at this location: <span id="totalqty">10</span></label>
                            <br>
                            <div id="destination">
                                <div id="row" class="row">
                                    <button type="button" class="decrement">-</button>
                                    <input type="text" class="quantity" value="0" readonly/>
                                    <button type="button" class="increment">+</button>
                                    <a>Location: </a>
                                    <input type="text" class="location" value="0" readonly/>
                                </div>
                            </div>
                        </form>

                        <label>Total being transfer: <p id="total-sum"></p></label>
                        <br>
                        <button type="button" id="addlocationdest">ADD</button>
            <button type="button" id="removelocationdest">REMOVE</button>
                </div>

【问题讨论】:

  • 总量的数字是动态的吗?提交表格后如果超出总数应该减少多少?难道不能不增加行数,增加时会导致实际总量溢出给定的总量?
  • 是的,总数将是动态的,总数将减少,另一个分配给数据库中的特定行,但现在这并不重要。当我连续增加数字时,它会减少总数,总数仅供参考。将其视为该特定位置的当前数量
  • 所以总数不是下面数字的总数,而是仍然可以分配到下面数字的总数?
  • 就是这个数字将被分配,需要相应地更新
  • 是否可以通过键盘将数字写入输入字段,还是只能通过按钮更改值?允许通过键盘进行更改会使其变得相当复杂,但仍有可能。

标签: javascript html increment decrement


【解决方案1】:

序幕
只要总量在脚本执行开始时是固定的,就可以了。否则,最好将实际允许的总量保存为属性,并使用MutationObserver 观察它。这样你就可以更新你的最大值。当总数量属性发生变化时,您的代码中的值会动态变化。您可以通过将custom attributes 命名为“data-*”来定义custom attributes,其中“*”是自定义名称。

解决您的问题
您在多个元素上使用相同的 ID。你的意思是类,所以将id="increment" 更改为class="increment"decrement 也是如此。

由于我们不想通过按钮输入内容,而是为它们添加侦听器,我认为最好实际使用&lt;button&gt;。在表单中,按钮充当type="submit",这是我们不想要的,因此我们需要将其更改为type="button"

由于行和总数实际上属于一起,因此将它们一起放入 one &lt;form&gt;-element 更为明智。但是,您仍然可以使用 &lt;div&gt; 将按钮和输入组合成一行。

现在关于行值和总量的增加/减少:

  1. 将允许的总量保存在变量中
  2. 为相应的按钮添加事件监听器
  3. 如果操作有效,则更改行的值
  4. 更新总量为totalQuantity - getSumOfRows()

为了动态添加新行,我们创建并设置了这样一个元素,并将其附加到表单中。请参阅下面的appendNewRow()-函数。

旁注
我已将readonly 属性添加到输入字段,这样您就无法通过键盘输入数字。

window.addEventListener("load", () => {
  let elTotalQuantity = document.querySelector("#totalqty");
  let totalQuantity = parseInt(elTotalQuantity.innerHTML);
  
  function getSumOfRows() {
    let sum = 0;
    for (let input of document.querySelectorAll("form .row > input.quantity"))
      sum += parseInt(input.value);
    return sum;
  }
  function updateTotalQuantity() {
      elTotalQuantity.innerHTML = totalQuantity - getSumOfRows();
  }
  
  function appendNewRow() {
    let row = document.createElement("div");
    row.classList.add("row");
    let child;
    
    // input.quantity
    let input = document.createElement("input");
    input.classList.add("quantity");
    input.value = "0";
    input.setAttribute("readonly", "");
    input.setAttribute("type", "text");
    row.append(input);
    
    // button.increment
    child = document.createElement("button");
    child.classList.add("increment");
    child.innerHTML = "+";
    child.setAttribute("type", "button");
    child.addEventListener("click", () => {
      if (getSumOfRows() >= totalQuantity) return;
      input.value++;
      updateTotalQuantity();
    });
    row.append(child);
    
    // button.increment
    child = document.createElement("button");
    child.classList.add("decrement");
    child.innerHTML = "-";
    child.setAttribute("type", "button");
    child.addEventListener("click", () => {
      if (input.value <= 0) return;
      input.value--;
      updateTotalQuantity();
    });
    row.append(child);
    
    // button.remove-row
    child = document.createElement("button");
    child.classList.add("remove-row");
    child.innerHTML = "Remove";
    child.setAttribute("type", "button");
    child.addEventListener("click", () => {
      row.remove();
      updateTotalQuantity();
    });
    row.append(child);
    
    document.querySelector("form .rows").append(row);
  }
  
  document.querySelector("form .add-row").addEventListener("click", () => appendNewRow());
  
  appendNewRow();
});
<form>
  <label>Total Quantity: <span id="totalqty">10</span></label>
  <br>
  <div class="rows">
  </div>
  <button type="button" class="add-row">Add new row</button>
</form>

【讨论】:

  • 如果我们在行中添加第二个输入,第一个增量后总数量返回NaN
  • 您可以为包含数量的输入提供一个类似quantity 的类,然后进行查询。这样,它应该可以工作。更新了答案以包含我刚才所说的内容。
  • 如何将行中的值发送到数据库?我正在考虑使用类似 SELECT * FROM mytable where itemID=?? & location=??.. 如果返回 1 -> 更新值,如果返回 0 -> 插入并创建新行
  • 看起来您正在使用 SQL 数据库。您的想法似乎足以满足我认为您正在努力实现的目标。但要获得更好的答案,您应该打开一个新问题。
  • 是的,我确实在使用 MySQL 非常感谢,如果你想看看这里的问题是链接stackoverflow.com/questions/64761304/…
【解决方案2】:

QuerySelector 只选择第一个匹配项,因此您还没有真正将侦听器添加到第二个“行”。您应该使用 querySelectorAll,但不要使用唯一 ID,而是使用类。

<input class="increment" type="button" value="+" />
  1. 现在您可以使用document.querySelectorAll(".increment") 获取数组中的所有元素。

  2. 您可以使用parentElement 遍历DOM。通过知道您单击了哪个按钮,您可以遍历表单元素,然后选择第一个子元素 - 这是一个输入。一种更动态的方法是使用querySelector 来选择输入,以防将来HTML 发生变化。无论如何,这就是您可以根据按钮在 DOM 中的位置来知道要操作哪个输入的方法。

  3. 我添加了两个全局变量totalSummaxSummaxSum 是从您的 span 元素中获取的(我为其分配了一个唯一的 id)。 totalSum 确保所有输入组合不超过 maxSum

  4. 你有一些重复的代码,所以我将它重构为一个新方法:changeValue

总之,我认为代码不言自明。

哦,这段代码没有考虑到用户可以更改输入中的值。我会留给您在每个文本输入上使用“oninput”侦听器来弄清楚。

var totalSum = 0;  // 3
var maxSum = 0
var totalSumElement = null;

document.addEventListener('DOMContentLoaded', async function() {
  totalSumElement = document.getElementById('total-sum');
  maxSum = document.getElementById('max-sum').innerText;

  var incrementElements = document.querySelectorAll('.increment');  // 1
  var decrementElements = document.querySelectorAll('.decrement');

  addListener('click', incrementElements, incrementValue);
  addListener('click', decrementElements, decrementValue);
});


function addListener(type, elementArr, func) {
  for (element of elementArr) {
    element.addEventListener(type, func);
  }
}

function withinRange(newValue) {
  var maxReached  = newValue > maxSum;  // 3
  var zeroReached = newValue < 0;

  return !maxReached && !zeroReached;
}

function changeValue(event, change) {  // 4
  if (withinRange(totalSum + change)) {
    let parent = event.currentTarget.parentElement;  // 2
    let input  = parent.children[0];
    let value  = parseInt(input.value) || 0;
    
    if (withinRange(value + change)) {
      input.value = value + change;
      totalSum = totalSum + change;
    }
  }

  totalSumElement.textContent = `Total: ${totalSum}`;
}

function incrementValue(event) {
  changeValue(event, 1);
}

function decrementValue(event) {
  changeValue(event, -1);
}
#totalqty {
  padding-bottom: 1rem;
}
<div id="totalqty" class="line padded-s">Total Quantity: <span id="max-sum">10</span></div>

<form>
  <input type="text" value="0" />
  <input class="increment" type="button" value="+" />
  <input class="decrement" type="button" value="-" />
</form>
<form>
  <input type="text" value="0" />
  <input class="increment" type="button" value="+" />
  <input class="decrement" type="button" value="-" />
</form>

<p id="total-sum"></p>

【讨论】:

  • 我已经有一个名为 addListener 的函数,如果我重命名你的函数,我得到一个错误 ReferenceError: element is not defined
  • 如果是这种情况,您需要调试。将debugger; 添加到重命名的addListener 方法中,并在浏览器中打开Web Developer Console 的情况下运行该页面。出于某种原因,elementArr 是空的。也可以console.log()incrementElementsdecrementElements查看数组是否为空。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-20
  • 1970-01-01
  • 1970-01-01
  • 2012-02-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多