使用 jQuery/AJAX 从 JSON 数据中过滤带有复选框的结果

Posted

技术标签:

【中文标题】使用 jQuery/AJAX 从 JSON 数据中过滤带有复选框的结果【英文标题】:Filtering results with checkboxes from JSON data using jQuery/AJAX 【发布时间】:2021-10-01 19:26:58 【问题描述】:

我正在尝试制作具有高级过滤功能的搜索页面。董事、评级和年份应显示在侧边栏上,不得重复。选中一个框时,包含电影的过滤结果应显示在同一页面上,然后在没有选中框时消失。

例如,您应该能够选中“弗朗西斯·福特·科波拉”框并获得由他执导的电影列表(“教父”和“局外人”),或者如果您单击复选框进行评级5 同样,您应该只获得“教父”等。

我从来没有使用过 ajax 或 javascript,并且在 php 方面的经验非常有限,所以我很难让任何事情发挥作用

这是端点 api.php?films 中包含的 JSON 数据的摘录,其中包含 100 部影片:

[
    
        "film": "The Bridge on the River Kwai",
        "director": "David Lean",
        "rating": "2",
        "year": "1957"
    ,
    
        "film": "A Night To Remember",
        "director": "Roy Ward Baker",
        "rating": "2",
        "year": "1958"
    ,
        "film": "The Outsiders",
        "director": "Francis Ford Coppola",
        "rating": "4",
        "year": "1983"
    ,
    
        "film": "Asylum",
        "director": "Roy Ward Baker",
        "rating": "3",
        "year": "1966"
    ,
    
        "film": "Trading Places",
        "director": "John Landis",
        "rating": "5",
        "year": "1983"
    ,
    
        "film": "The Godfather",
        "director": "Francis Ford Coppola",
        "rating": "5",
        "year": "1983"
    
 
]

这是我用复选框显示年份的代码,但我需要没有重复的年份(我需要不同的 GET 请求来仅显示年份的唯一值吗?)。至于过滤和显示结果的 JavaScript,我真的需要帮助。


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script
  src="https://code.jquery.com/jquery-3.6.0.min.js"
  integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4="
  crossorigin="anonymous"></script>
  
</head>
<body>

<h1>Filter films by year</h1>
<div id='items-container'>

</div>


<script>

$.ajax(
        url: "api.php",
        method: "GET",
        dataType: 'json',
        data: 'films',
        success: function(data) 
          console.log(typeof(data));
          var html_to_append = '';
          $.each(data, function(i, item) 
            html_to_append +=
            '<div class="col-3 mb-3"><p>' +
            item.year +
            '<input type="checkbox"></p></div>';
          );
          $("#items-container").html(html_to_append);
        ,
        error: function() 
          console.log(data);
        
      );



    </script>

</body>
</html>

任何帮助将不胜感激,因为我已经尝试这样做了一段时间。

【问题讨论】:

【参考方案1】:

您可以执行以下操作来为条件“导演”、“评级”和“年份”生成过滤条件:

const data=["film":"The Bridge on the River Kwai","director":"David Lean","rating":"2","year":"1957",
            "film":"A Night To Remember","director":"Roy Ward Baker","rating":"2","year": "1958",
            "film":"The Outsiders","director":"Francis Ford Coppola","rating":"4","year": "1983",
            "film":"Asylum","director":"Roy Ward Baker","rating":"3","year": "1966",
            "film":"Trading Places","director":"John Landis","rating":"5","year": "1983",
            "film":"The Godfather","director":"Francis Ford Coppola","rating":"5","year": "1983"];

// define globally: constants, variables and delegated event attachment:
// ---------------------------------------------------------------------
const filt=document.getElementById("filt"),
      list=document.querySelector("#list tbody");
let cols=, trs; // arrays for columns sequence in data and all table records
      
// set up filtering (needs be done only once, before the AJAX call):
filt.addEventListener("change",ev=>let cb=ev.target;
  let tst=Object.entries([...filt.querySelectorAll(":checked")].reduce((a,c)=>((a[c.name]=a[c.name]||[]).push(c.value),a), ));
  trs.forEach(tr=>
   tr.style.display=tst.length==0 || tst.every(([n,arr])=>arr.includes(tr.children[cols[n]].textContent)) 
     ?"":"none"
  )
);      
      

// put the following code into the "success" function of your AJAX call: 
// ---------------------------------------------------------------------
if (data.length)  // only if data array is not empty
 // columns sequence:
 Object.keys(data[0]).forEach((c,i)=>cols[c]=i);
 // build the filter-menu structure:
 const menu=director:,rating:,year:;
       data.forEach(f=>Object.entries(menu).forEach(([k,o])=>o[f[k]]=1));

 // translate the filter-menu structure into HTML:
 filt.innerHTML=Object.entries(menu).map(([k,o])=>k+':<br>'+
   Object.keys(o).map(c=>'<label><input type="checkbox" value="'+c+'" name="'+k+'">'+c+'</label>').join('<br>')
 ).join('<br>\n');

 // fill the main film list with data entries:
 list.innerHTML=data.map(f=>'<tr><td>'+Object.values(f).join('</td><td>')+'</td></tr>').join('\n');
 trs=[...list.children];
#filt width: 200px; display:inline-block
#list display:inline-block; vertical-align:top
th text-align:left
tbody>tr:nth-child(odd) background-color:#ddd
<div id="filt"></div>
<div id="list"><table><thead><tr><th>Title</th><th>Director</th><th>Rating</th><th>Year</th></tr></thead>
<tbody></tbody></table</tdiv>

您可能已经注意到,将这些放在一起花了我一段时间,我分几期完成了。在编码中,我经常写东西,看看它,然后很快又把它扔掉。对我来说,设计需要流畅地发展,允许频繁重写,直到“最终”(没有这样的东西?)布局类似于我正在寻找的。​​p>

【讨论】:

这正是我所需要的,谢谢!【参考方案2】:

年份不应是复选框,而应是用户可以输入的文本框(四字符数字)。 API 调用应使用参数,如年份(文本框)、评级(选择)、导演(文本框)等来过滤电影,而不是一次调用 100 部电影。 您还可以对导演和头衔进行自动完成,当用户填写字段时,API 仅检索导演或头衔。

【讨论】:

以上是关于使用 jQuery/AJAX 从 JSON 数据中过滤带有复选框的结果的主要内容,如果未能解决你的问题,请参考以下文章

从 JQuery.ajax 成功数据中解析 JSON

dataType json 的 jQuery $.ajax 请求不会从 PHP 脚本中检索数据

使用jQuery $ .ajax方法显示包含MySQL表数据的JSON [关闭]

如何从MVC5中的jquery ajax调用中获取部分视图和JSON数据?

无法从 JQuery ajax 调用接收 JSON

jQuery Ajax 调用返回 JSON 字符串而不是对象数组