【问题标题】:Javascript, match checkboxes with JSONJavascript,将复选框与 JSON 匹配
【发布时间】:2019-07-03 19:08:36
【问题描述】:

我有:

  • 多个复选框
  • 提交按钮
  • 一个 JSON 字符串对象。
  • 一个检查哪些复选框被选中的函数,并在我的提交按钮上使用一个事件监听器在警报或 console.log 中返回它们的值。
  • 输出 DIV

如何比较从检查哪些复选框被选中的函数获得的值与 JSON 字符串对象中的值,并将它们回显到输出 DIV 中?假设我选中了“Cheese”和“Garlic”框,并期望收到以下输出:

  • 食谱 1:奶酪、番茄、大蒜
  • 食谱 2:奶酪、土豆、蛋黄酱、牛肉、大蒜、黄油

HTML:

<form action="" method="">
    <input type="checkbox" value="Cheese">Cheese<br>
    <input type="checkbox" value="Tomato">Tomato<br>
    <input type="checkbox" value="Garlic">Garlic<br>
    <input type="checkbox" value="Bacon">Bacon<br>
    <input type="checkbox" value="Paprika">Paprika<br>
    <input type="checkbox" value="Onion">Onion<br>
    <input type="checkbox" value="Potato">Potato<br>
    <input type="checkbox" value="Mayo">Mayo<br>
    <input type="checkbox" value="Beef">Beef<br>
    <input type="checkbox" value="Garlic">Garlic<br>
    <input type="checkbox" value="Butter">Butter<br>

    <input type="button" value="Get recipes" id="getRecipesButton">
</form>

<div id="output">The results end up here</div>

JS:

//Recipes JSON-string:
var recipes = [
    {
        name:"recipe1",
        ingredients:
            [
                {ingredient:"Cheese"},
                {ingredient:"Tomato"},
                {ingredient:"Garlic"}
            ]
    },
    {
        name:"recipe2",
        ingredients:
            [
                {ingredient:"Cheese"},
                {ingredient:"Bacon"},
                {ingredient:"Paprika"},
                {ingredient:"Onion"}
            ]
    },
    {
        name:"recipe3",
        ingredients:
            [
                {ingredient:"Cheese"},
                {ingredient:"Potato"},
                {ingredient:"Mayo"},
                {ingredient:"Beef"},
                {ingredient:"Garlic"},
                {ingredient:"Butter"}
            ]
    }
];
//Test to retrieve single, specific entries: 
//      console.log(recipes[1].ingredients[0].ingredient);


//Test to get/return the checked values of the checkboxes:
function selectedBoxes(form) {
    let selectedBoxesArr = [];
    let inputFields = form.getElementsByTagName('input');
    let inputFieldsNumber = inputFields.length;

    for(let i=0; i<inputFieldsNumber; i++) {
        if(
            inputFields[i].type == 'checkbox' &&
            inputFields[i].checked == true
        ) selectedBoxesArr.push(inputFields[i].value);
    }
    return selectedBoxesArr;
}

var getRecipesButton = document.getElementById('getRecipesButton');
getRecipesButton.addEventListener("click", function(){
    let selectedCheckBoxes = selectedBoxes(this.form);
    alert(selectedCheckBoxes);
});

>>Fiddle

【问题讨论】:

    标签: javascript json checkbox lookup


    【解决方案1】:

    这是一种可以根据当前结构设置值的方法。请记住,在任何给定时间都不清楚您要应用什么配方,因此下面的代码会将第一个配方应用于表单。

    //Recipes JSON-string:
    var recipes = [{
        name: "recipe1",
        ingredients: [{
            ingredient: "Cheese"
          },
          {
            ingredient: "Tomato"
          },
          {
            ingredient: "Garlic"
          }
        ]
      },
      {
        name: "recipe2",
        ingredients: [{
            ingredient: "Cheese"
          },
          {
            ingredient: "Bacon"
          },
          {
            ingredient: "Paprika"
          },
          {
            ingredient: "Onion"
          }
        ]
      },
      {
        name: "recipe3",
        ingredients: [{
            ingredient: "Cheese"
          },
          {
            ingredient: "Potato"
          },
          {
            ingredient: "Mayo"
          },
          {
            ingredient: "Beef"
          },
          {
            ingredient: "Garlic"
          },
          {
            ingredient: "Butter"
          }
        ]
      }
    ];
    
    var getRecipesButton = document.getElementById('getRecipesButton');
    getRecipesButton.addEventListener("click", function() {
      for (let ingredient of recipes[0].ingredients) {
        document.querySelector(`input[value='${ingredient.ingredient}']`).setAttribute('checked', true);
      }
    });
    <form action="" method="">
      <input type="checkbox" value="Cheese">Cheese<br>
      <input type="checkbox" value="Tomato">Tomato<br>
      <input type="checkbox" value="Garlic">Garlic<br>
      <input type="checkbox" value="Bacon">Bacon<br>
      <input type="checkbox" value="Paprika">Paprika<br>
      <input type="checkbox" value="Onion">Onion<br>
      <input type="checkbox" value="Potato">Potato<br>
      <input type="checkbox" value="Mayo">Mayo<br>
      <input type="checkbox" value="Beef">Beef<br>
      <input type="checkbox" value="Garlic">Garlic<br>
      <input type="checkbox" value="Butter">Butter<br>
    
      <input type="button" value="Get recipes" id="getRecipesButton">
    </form>
    
    <div id="output">The results end up here</div>

    如果您有任何问题,请随时发表评论

    【讨论】:

      【解决方案2】:

      你觉得这个快速建议怎么样,我知道它不是很优雅:

      HTML(用这个替换)

      <ul id="output">The results end up here</ul>
      

      JS

      var getRecipesButton = document.getElementById('getRecipesButton');
      getRecipesButton.addEventListener("click", function(){
          let selectedCheckBoxes = selectedBoxes(this.form);
          document.getElementById("output").innerHTML = "";
        var res = [];
        recipes.forEach(function(r,k){
          r['ingredients'].forEach(function(i,idx){
              if(selectedCheckBoxes.includes(i.ingredient)) {
              res.push(r);
            }
          });
        });
      // remove duplicate then display the recipe with the ingredient
          res.filter(function(item, index){
            return res.indexOf(item) >= index;
          }).forEach(function(r){
            var ingredient = r.ingredients.map(function(r) { return r.ingredient}).join(", ");
            var name = r.name + " : "+ingredient ;
            var ul = document.getElementById("output");
            var li = document.createElement('li');
            li.appendChild(document.createTextNode(name));
            ul.appendChild(li);
          });
      });
      

      这里是一个工作版本:https://jsfiddle.net/8esvh65p/

      【讨论】:

      • 太棒了!那绝对成功了。其他答案返回数组(即不是完整的解决方案)。不过,我也得到了其他答案的价值,如果我需要更改功能,我可以使用它们。我还将提交按钮调整为不可见(零高度、宽度、填充和边距),并将其包装在复选框的事件监听器中,因此每当有人选中或取消选中某个框时,它都会立即更新。
      • 不客气。顺便说一句,我确信我们可以“优化”代码,但也许以后再说。
      • 也许吧。老实说,我认为它非常简短和整洁。但我会用这个工作一段时间,因为它将作为我个人的食谱查找根据我手头的成分进行购物,所以我相信我会发现自己处于我想要或需要的情况一路更新它(大多数事情通常都是这种情况)。
      【解决方案3】:

      您可以将您的食谱数组过滤为仅包含所有选定成分的食谱,如下所示:

      let filtered = recipes.filter((recipe) => {
          return selectedCheckBoxes.every((selected) => {
              return recipe.ingredients.some((ingredient) => {
                  return ingredient['ingredient'] === selected;
              });
          });
      });
      

      因此,对于每个食谱,我们都会检查每种所选成分是否包含在食谱中。在这种情况下:

      • filter(): 过滤掉任何不包含所有选定成分的食谱;
      • every(): 检查每个选择的成分是否在当前由 filter() 评估的配方中;
      • some(): 检查配方的某些成分是否等于 every() 评估的当前选择成分。

      我编辑了你的小提琴,所以你可以看到它工作:https://jsfiddle.net/byce6vwu/1/

      编辑

      您可以像这样将返回的数组转换为html(我还将输出div更改为ul

      let outputRecipes = '';
        filtered.forEach((recipe) => {
          let stringIngredients = recipe.ingredients.map((val) => {
              return val.ingredient;
          }).join(',');
              outputRecipes += `<li>${recipe.name}: ${stringIngredients}</li>`;
        });
          document.getElementById('output').innerHTML = outputRecipes;
      

      我已经编辑了小提琴:https://jsfiddle.net/ys0qofgm/

      因此,对于数组中的每个成分,我们将成分对象:{ingredient: "Cheese"} 转换为仅字符串 "Cheese",并使用逗号作为分隔符连接数组的所有元素。然后为每个配方创建一个 li 元素,并将配方字符串放入其中。

      【讨论】:

      • 谢谢!当它返回数组时,我没有选择它作为解决方案,尽管它在某种程度上绝对符合我的要求。我赞成它,因为它有用的并且教会了我一些东西!
      • 关于如何输出数组和返回的内部数组有什么建议吗?
      • 我已经编辑了如何做你想做的事情的答案。
      • 太棒了!不能感谢你。现在我有了更好的工具来研究如何自己制作这样的东西。
      【解决方案4】:

      此代码将执行您想要的操作。它遍历每种成分,检查食谱集及其成分以检查该食谱是否包含该成分。仅返回包含所有所选成分的食谱:

      //Recipes JSON-string:
      var recipes = [
      	{
      		name:"recipe1",
      		ingredients:
      			[
      				{ingredient:"Cheese"},
      				{ingredient:"Tomato"},
      				{ingredient:"Garlic"}
      			]
      	},
      	{
      		name:"recipe2",
      		ingredients:
      			[
      				{ingredient:"Cheese"},
      				{ingredient:"Bacon"},
      				{ingredient:"Paprika"},
      				{ingredient:"Onion"}
      			]
      	},
      	{
      		name:"recipe3",
      		ingredients:
      			[
      				{ingredient:"Cheese"},
      				{ingredient:"Potato"},
      				{ingredient:"Mayo"},
      				{ingredient:"Beef"},
      				{ingredient:"Garlic"},
      				{ingredient:"Butter"}
      			]
      	}
      ];
      //Test to retrieve single, specific entries:
      //      console.log(recipes[1].ingredients[0].ingredient);
      
      
      //Test to get/return the checked values of the checkboxes:
      function selectedBoxes(form) {
      	let selectedBoxesArr = [];
      	let inputFields = form.getElementsByTagName('input');
      	let inputFieldsNumber = inputFields.length;
      
      	for(let i=0; i<inputFieldsNumber; i++) {
      		if(
      			inputFields[i].type == 'checkbox' &&
      			inputFields[i].checked == true
      		) selectedBoxesArr.push(inputFields[i].value);
      	}
      	return selectedBoxesArr;
      }
      
      var getRecipesButton = document.getElementById('getRecipesButton');
      getRecipesButton.addEventListener("click", function(){
        let selectedCheckBoxes = selectedBoxes(this.form);
        let output = document.getElementById('output');
        let myRecipes = recipes.filter(r => 
          selectedCheckBoxes.every(s => 
             r.ingredients.some(i => i.ingredient == s)
          )
        );
        output.innerHTML = myRecipes.map(v => v.name + ': ' + v.ingredients.map(i => i.ingredient).join(', ')).join('<br>');
      });
      <form action="" method="">
      	<input type="checkbox" value="Cheese">Cheese<br>
      	<input type="checkbox" value="Tomato">Tomato<br>
      	<input type="checkbox" value="Garlic">Garlic<br>
      	<input type="checkbox" value="Bacon">Bacon<br>
      	<input type="checkbox" value="Paprika">Paprika<br>
      	<input type="checkbox" value="Onion">Onion<br>
      	<input type="checkbox" value="Potato">Potato<br>
      	<input type="checkbox" value="Mayo">Mayo<br>
      	<input type="checkbox" value="Beef">Beef<br>
      	<input type="checkbox" value="Garlic">Garlic<br>
      	<input type="checkbox" value="Butter">Butter<br>
      
      	<input type="button" value="Get recipes" id="getRecipesButton">
      </form>
      
      <div id="output">The results end up here</div>

      【讨论】:

      • 太棒了!虽然它不输出成分并且只输出匹配的成分,但它有效,而不是全部。
      • @Strechingmycompetence 对此感到抱歉 - 我没有仔细阅读这个问题。为了完整起见,我更新了答案以提供您要求的输出。
      • 没有压力!我喜欢各种各样的方法。它给了我对未来的希望和继续学习的动力:D
      【解决方案5】:

      我编辑了您的代码并使其更小,还添加了getRecipe,它将返回食谱。

      //Recipes JSON-string:
      var recipes = [
          {
              name:"recipe1",
              ingredients:
                  [
                      {ingredient:"Cheese"},
                      {ingredient:"Tomato"},
                      {ingredient:"Garlic"}
                  ]
          },
          {
              name:"recipe2",
              ingredients:
                  [
                      {ingredient:"Cheese"},
                      {ingredient:"Bacon"},
                      {ingredient:"Paprika"},
                      {ingredient:"Onion"}
                  ]
          },
          {
              name:"recipe3",
              ingredients:
                  [
                      {ingredient:"Cheese"},
                      {ingredient:"Potato"},
                      {ingredient:"Mayo"},
                      {ingredient:"Beef"},
                      {ingredient:"Garlic"},
                      {ingredient:"Butter"}
                  ]
          }
      ];
      
      function selectedBoxes(form) {
          let selectedBoxesArr = [];
          let inputFields = form.getElementsByTagName('input');
          // get all checked input values
          var checked = [...inputFields].filter((item) => item.checked == true
          ).map((item) => item.value)
          return checked;
      }
      
      // Validate the checked ingredients and get the recipes
      function getRecipe(ingredients){
      var recipe = [];
      recipes.forEach((item)=> {
      var found= false;
      for(var ingredient in ingredients){
         var y = ingredients[ingredient]
         found= item.ingredients.filter((x) =>  x.ingredient.indexOf(y) != -1).length>0;
        if (!found)
            break;
          }
        if(found)
           recipe.push(item.name +":"+ item.ingredients.map((x)=> x.ingredient).join(", "));
      });
      return recipe;
      }
      
      var getRecipesButton = document.getElementById('getRecipesButton');
      getRecipesButton.addEventListener("click", function(){
          let selectedCheckBoxes = selectedBoxes(this.form);
          console.log(getRecipe(selectedCheckBoxes))
      });
      <form action="" method="">
          <input type="checkbox" value="Cheese">Cheese<br>
          <input type="checkbox" value="Tomato">Tomato<br>
          <input type="checkbox" value="Garlic">Garlic<br>
          <input type="checkbox" value="Bacon">Bacon<br>
          <input type="checkbox" value="Paprika">Paprika<br>
          <input type="checkbox" value="Onion">Onion<br>
          <input type="checkbox" value="Potato">Potato<br>
          <input type="checkbox" value="Mayo">Mayo<br>
          <input type="checkbox" value="Beef">Beef<br>
          <input type="checkbox" value="Garlic">Garlic<br>
          <input type="checkbox" value="Butter">Butter<br>
      
          <input type="button" value="Get recipes" id="getRecipesButton">
      </form>
      
      <div id="output">The results end up here</div>

      【讨论】:

      • 谢谢!我赞成你的回答,因为它有用的并且教会了我一些东西,虽然它似乎只返回它找到的第一个配方和其余的数组。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多