【问题标题】:Filtering results with checkboxes from JSON data using jQuery/AJAX使用 jQuery/AJAX 从 JSON 数据中过滤带有复选框的结果
【发布时间】: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>

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

【问题讨论】:

    标签: javascript php jquery json ajax


    【解决方案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 仅检索导演或头衔。

    【讨论】:

      猜你喜欢
      • 2011-06-28
      • 2015-07-10
      • 2017-01-15
      • 2020-06-10
      • 2016-07-21
      • 1970-01-01
      • 1970-01-01
      • 2019-10-20
      • 2013-09-22
      相关资源
      最近更新 更多