删除动态创建的表单元素

Deleting dynamically created form elements

我一直在尝试制作一个动态表单,以便用户可以在他们提交的表单中添加一系列成分。我能够动态添加输入元素,但也想动态删除它们。我正在尝试使用基本 javascript 而不是 jquery 来完成所有这些工作。我 运行 的问题是,如果我将我的删除按钮片段放在 addBtn 单击事件中,我只能删除我选择的一项。如果我尝试将片段放在单击事件之外,我将无法通过 querySelectorAll 获取我想要的元素数组,因为查询是在 addBtn 事件侦听器关闭之前和元素创建之前进行的。提前致谢!

const ingredients = () => {
  const container = document.querySelector(".show-ingredients");
  const addBtn = document.querySelector(".add-ingredient");
  const newIngredient = document.querySelector("#input-ingredients");
  let ingredients = [];
  newIngredient.required = true;
  addBtn.addEventListener("click", async() => {
    newIngredient.required = false;
    ingredients.push(`
        <div class="ingredient-container">
            <input class='ingredient' type="text" value='${newIngredient.value}' required >
            <div class="controls delete">
                <a class="delete-ingredient">
                    <span class="ingredient-bar"></span>
                </a>
            </div>
        </div>`);
    container.innerHTML = ingredients.join("");
    newIngredient.value = "";
  });
  var deleteBtn = document.querySelectorAll(".delete-ingredient");
  console.log(deleteBtn);
  for (let i = 0; i < deleteBtn.length; i++) {
    deleteBtn[i].addEventListener("click", async() => {
      console.log(i);
      // ingredients.splice(i, 1);
      // container.innerHTML = ingredients.join('');
    });
  }
  if (ingredients.length == 0) {
    newIngredient.required = true;
  }
};
ingredients();
.form-container {
  display: flex;
  text-align: center;
  flex-direction: column;
  text-align: center;
  justify-content: center;
  align-items: center;
  transition: all 0.5s ease-in-out;
}

.form-container input {
  width: 400px;
  max-width: 100%;
  height: 40px;
  padding-left: 10px;
  margin-bottom: 5px;
}


/* Add/delete ingredient */

.ingredient-wrapper {
  width: 400px;
  max-width: 100%;
  display: flex;
  flex-direction: column;
}

.ingredient-container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 40px;
  width: 400px;
  max-width: 100%;
  border: 1px solid grey;
  margin-bottom: 5px;
}

.controls,
.controls.delete {
  background-color: green;
  height: 100%;
  width: 28px;
  padding-left: 1px;
}

.controls.delete {
  background-color: red;
}

.ingredient {
  margin-bottom: 0px;
  width: 100%;
  height: 100%;
  background: none;
}

.add-ingredient,
.delete-ingredient {
  width: 28px;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  transition: 0.5s ease-in-out;
  cursor: pointer;
}

.ingredient-bar::before {
  content: "";
  background-color: white;
  display: block;
  height: 2px;
  width: 13px;
  transform: rotate(90deg);
}

.ingredient-bar {
  background-color: white;
  height: 2px;
  width: 13px;
}

.delete-ingredient {
  background-color: red;
}

.delete-ingredient .ingredient-bar::before {
  display: none;
}
<form action="" class="form-container" id="wrapper">
  <input type="text" placeholder="What's cookin?" id="input-title" style="margin-top: 20px;" required>
  <div class="ingredient-wrapper">
    <div class="ingredient-container">
      <input type="text" placeholder="Ingredients" id="input-ingredients" style="border: none; margin-bottom: 0px; width: 400px;max-width:100%; height: 100%;">
      <div class="controls">
        <a class="add-ingredient">
          <span class="ingredient-bar"></span>
        </a>
      </div>
    </div>
    <div class="show-ingredients"></div>
  </div>
  <input type="text" placeholder="Description/Instructions" id="input-description" required>
  <button type="submit" class="add-btn">Add post</button>
</form>

Codepen 示例:https://codepen.io/benleem/pen/gOxgXWL(css 乱七八糟,但功能相同)

您应该能够通过将 .delete-ingredient selector 和 addEventListener 移动到一个单独的函数中来获得所需的结果。

这是一个片段,它记录了 deletBtn 数组中的位置。我没有更改 HTML 或 CSS。我要补充的另一个小注意事项是成分数组没有正确连接到删除按钮,因为您每次都重新声明该数组(全局数组与本地数组)。但是,您实际上并不需要该数组,因为您可以使用 deleteBtn[i] select 特定元素,然后可以使用 JavaScript .removeChild 功能将其删除。

const ingredients = () => {
  const container = document.querySelector(".show-ingredients");
  const addBtn = document.querySelector(".add-ingredient");
  const newIngredient = document.querySelector("#input-ingredients");
  let ingredients = [];
  newIngredient.required = true;
  addBtn.addEventListener("click", async () => {
    newIngredient.required = false;
    ingredients.push(`
        <div class="ingredient-container">
            <input class='ingredient' type="text" value='${newIngredient.value}' required >
            <div class="controls delete">
                <a class="delete-ingredient">
                    <span class="ingredient-bar"></span>
                </a>
            </div>
        </div>`);
    container.innerHTML = ingredients.join("");
    newIngredient.value = "";
    deleteIngredient(ingredients, container);
  });
  if (ingredients.length == 0) {
    newIngredient.required = true;
  }
};

const deleteIngredient = (list, wrapper) =>{
    let ingredients = list;
    let container = wrapper;
    var deleteBtn = document.querySelectorAll('.delete-ingredient');
    for (let i = 0; i < ingredients.length; i++) {
        deleteBtn[i].addEventListener('click', async () =>{
            console.log(i);
            ingredients.splice(i, 1);
            container.innerHTML = ingredients.join('');
          
            deleteIngredient(ingredients, container);
        });
    }
}

ingredients();
.form-container {
  display: flex;
  text-align: center;
  flex-direction: column;
  text-align: center;
  justify-content: center;
  align-items: center;
  transition: all 0.5s ease-in-out;
}

.form-container input {
  width: 400px;
  max-width: 100%;
  height: 40px;
  padding-left: 10px;
  margin-bottom: 5px;
}

/* Add/delete ingredient */

.ingredient-wrapper {
  width: 400px;
  max-width: 100%;
  display: flex;
  flex-direction: column;
}

.ingredient-container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 40px;
  width: 400px;
  max-width: 100%;
  border: 1px solid grey;
  margin-bottom: 5px;
}

.controls,
.controls.delete {
  background-color: green;
  height: 100%;
  width: 28px;
  padding-left: 1px;
}

.controls.delete {
  background-color: red;
}

.ingredient {
  margin-bottom: 0px;
  width: 100%;
  height: 100%;
  background: none;
}

.add-ingredient,
.delete-ingredient {
  width: 28px;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  transition: 0.5s ease-in-out;
  cursor: pointer;
}

.ingredient-bar::before {
  content: "";
  background-color: white;
  display: block;
  height: 2px;
  width: 13px;
  transform: rotate(90deg);
}

.ingredient-bar {
  background-color: white;
  height: 2px;
  width: 13px;
}

.delete-ingredient {
  background-color: red;
}

.delete-ingredient .ingredient-bar::before {
  display: none;
}
<form action="" class="form-container" id="wrapper">
  <input type="text" placeholder="What's cookin?" id="input-title" style="margin-top: 20px;" required>
  <div class="ingredient-wrapper">
    <div class="ingredient-container">
      <input type="text" placeholder="Ingredients" id="input-ingredients" style="border: none; margin-bottom: 0px; width: 400px;max-width:100%; height: 100%;">
      <div class="controls">
        <a class="add-ingredient">
          <span class="ingredient-bar"></span>
        </a>
      </div>
    </div>
    <div class="show-ingredients"></div>
  </div>
  <input type="text" placeholder="Description/Instructions" id="input-description" required>
  <button type="submit" class="add-btn">Add post</button>
</form>