有没有一种方法可以搜索JSON数组中的字段,该字段可以包含一个特定值的多个值?

时间:2019-11-22 13:20:54

标签: javascript json ajax rest

我有一个返回结果的ajax查询,应将其显示在html表中,如下所示:

<input type="button" value="Customer" onclick="SelectCustomer()">
<input type="button" value="Advisor" onclick="SelectAdvisor()">
<input type="button" value="Get Results" onclick="GetResults()">
<table id="results">
</table>

我想根据受影响的区域对此进行过滤,以便仅列出状态为“打开”的项目,并且仅影响特定区域,例如“顾问”或“客户”等。我必须执行的当前代码就过滤状态而言,此方法有效,但是当我尝试过滤“受影响的区域”字段时,我只会得到空的回报。我一直在使用JavaScript变量来包含有关是否已选择值的信息,这是我要过滤的内容,但是我所使用的过滤脚本仅显示Status值为Open的项目不会如果我在该字段中有多个值,似乎对我不起作用。

var dResponse = [
    {"Reference": "123456","Status": "Open","AffectedArea": ["IT","Advisor"]}
    {"Reference": "654321","Status": "Closed","AffectedArea": ["Customer","IT"]}
    {"Reference": "567889","Status": "Open","AffectedArea": ["Advisor","Customer"]}
    {"Reference": "987654","Status": "Open","AffectedArea": ["Customer"]}
]
var custSelect = "Unselected";
var adviSelect = "Unselected";
var custfil = "";
var advifil = "";

function SelectCustomer(){
    if (custSelect == "Unselected") {
        custSelect = "Selected";
        adviSelect = "Unselected";
    } else {
        custSelect = "Unselected";
    }
}
function SelectAdvisor(){
    if (adviSelect == "Unselected") {
        adviSelect = "Selected";
        custSelect = "Unselected";
    } else {
        adviSelect = "Unselected";
    }
}

function GetResults() {
    var results = document.getElementById("results");
    var filResponse = dResponse.filter(function(item){
        return item.Status == "Open";
    })
    if (custSelect == "Selected"){
        FilterCust();
    }
    if (adviSelect ==" Selected"){
        FilterAdvi();
    }
    results.innerHTML += "<tr><td>Reference</td><td>Status</td><td>Affected Area</td></tr>";
    for(var obj in filResponse){
        results.innerHTML += "<tr><td>" + dResponse[obj].Reference + "</td><td>" + dResponse[obj].Status + "</td><td>" + dResponse[obj].AffectedArea + "</td></tr>";
    }
}

function FilterCust() {
 filResponse = dResponse.filter(function(item){
  return item.ImpactedArea == "Customer";
})
}
function FilterAdvi() {
 filResponse = dResponse.filter(function(item){
  return item.ImpactedArea == "Advisor";
})
}

诚然,我不确定JSON结果如何在同一个字段中显示多个值,但是结果来自REST查询到SharePoint列表,并且脚本由此起作用,以上内容旨在提供有关JSON表中包含哪些数据。

1 个答案:

答案 0 :(得分:1)

而不是存储custSelectadviSelect的各个变量。我建议您将其存储到数组中。这样会更干净,更容易做。稍后,您可以利用数组some函数进行过滤。

<input type="button" value="Customer" onclick="handleOnChange(this.value)" />
<input type="button" value="Advisor" onclick="handleOnChange(this.value)" />
<input type="button" value="Get Results" onclick="GetResults()" />
<table id="results">
  <!-- Table content will be created with Javascript -->
</table>
<script>
  const dResponse = [
    {
      Reference: '123456',
      Status: 'Open',
      AffectedArea: ['IT', 'Advisor']
    },
    {
      Reference: '654321',
      Status: 'Closed',
      AffectedArea: ['Customer', 'IT']
    },
    {
      Reference: '567889',
      Status: 'Open',
      AffectedArea: ['Advisor', 'Customer']
    },
    {
      Reference: '987654',
      Status: 'Open',
      AffectedArea: ['Customer']
    }
  ];

  let selectedArea = [];
  const handleOnChange = value => {
    const index = selectedArea.findIndex(a => a === value);
    if (index > -1) {
      selectedArea.splice(index, 1);
    } else {
      selectedArea.push(value);
    }
  };

  const GetResults = () => {
    const results = document.getElementById('results');
    const filResponse = dResponse.filter(item => item.Status == 'Open' && selectedArea.some(a => item.AffectedArea.indexOf(a) > -1));
    results.innerHTML +=
      '<tr><td>Reference</td><td>Status</td><td>Affected Area</td></tr>';
    filResponse.forEach(item => {
      results.innerHTML +=
        '<tr><td>' +
        item.Reference +
        '</td><td>' +
        item.Status +
        '</td><td>' +
        item.AffectedArea +
        '</td></tr>';
    });
  };
</script>

更新(11/22/2019):

<!DOCTYPE html>
<html>
  <head>
    <style>
      .selected {
        background: yellow;
      }
    </style>
  </head>
  <meta charset="utf-8" />
  <body>
    <form onsubmit="GetResults(event)">
      <input type="button" name="AffectedArea" value="IT" onclick="handleToggleOnChange(this)" />
      <input type="button" name="AffectedArea" value="Customer" onclick="handleToggleOnChange(this)" />
      <input type="button" name="AffectedArea" value="Advisor" onclick="handleToggleOnChange(this)" />
      <select name="Status" onchange="handleSelectOnChange(this)">
        <option value="Open" selected="selected">Open</option>
        <option value="Closed">Closed</option>
      </select>
      <input type="submit" />
    </form>
    <table id="results">
      <!-- Table content will be created with Javascript -->
    </table>
    <script>
      const dResponse = [
        {
          Reference: "123456",
          Status: "Open",
          AffectedArea: ["IT", "Advisor"]
        },
        {
          Reference: "654321",
          Status: "Closed",
          AffectedArea: ["Customer", "IT"]
        },
        {
          Reference: "567889",
          Status: "Open",
          AffectedArea: ["Advisor", "Customer"]
        },
        {
          Reference: "987654",
          Status: "Open",
          AffectedArea: ["Customer"]
        }
      ];

      // Store form's filter data
      const formData = {
        AffectedArea: [],
        Status: 'Open',
      }

      const handleToggleOnChange = input => {
        const { name, value } = input;
        const index = formData[name].findIndex(a => a === value);
        if (index > -1) {
          input.classList.remove('selected');
          formData[name].splice(index, 1);
        } else {
          input.classList.add('selected');
          formData[name].push(value);
        }
        // Log your formData
        console.log(formData);
      };

      const handleSelectOnChange = (select) => {
        const { name, value } = select;
        formData[name] = value;
        // Log your formData
        console.log(formData);
      }

      const createRow = () => document.createElement("tr");

      const createColumn = (text, colspan) => {
        const column = document.createElement("td");
        const textNode = document.createTextNode(text);
        column.appendChild(textNode);
        column.setAttribute('colspan', colspan);
        return column;
      };

      const GetResults = (e) => {
        e.preventDefault();
        const results = document.getElementById("results");
        const filResponse = dResponse.filter(
          item =>
            // Status must be Open
            item.Status == formData.Status &&
            // Item's AffectedArea's array includes one of the selected area
            formData.AffectedArea.some(a => item.AffectedArea.indexOf(a) > -1)
        );
        // Clear previous result
        while (results.firstChild) {
          results.firstChild.remove();
        }
        // Create header row
        const headerRow = createRow();
        let headerKeys = [];
        if (dResponse.length > 0) {
          headerKeys = Object.keys(dResponse[0]);
          headerKeys.forEach(key => {
            headerRow.appendChild(createColumn(key));
          });
        }
        results.appendChild(headerRow);
        // Create content result rows
        if (filResponse.length > 0) {
          const rows = [];
          filResponse.forEach(item => {
            const row = createRow();
            Object.values(item).forEach(value => {
              row.appendChild(createColumn(value));
            });
            rows.push(row);
          });
          if (rows.length > 0) {
            rows.forEach(r => {
              results.appendChild(r);
            });
          }
        } else {
          // Create no results found row
          const row = createRow();
          row.appendChild(createColumn("No results found", headerKeys.length));
          results.appendChild(row);
        }
      };
    </script>
  </body>
</html>

我已经创建了一个简单的数组过滤实现示例。我尝试避免使用innerHTML,您可以使用自己的呈现方法。 进一步更新了我的答案,以提供更多选择。

正在运行的演示:https://codesandbox.io/s/html-filter-table-demo-qm19r?fontsize=14&hidenavigation=1&theme=dark