Wordpress 过滤多个下拉分类以通过 ajax 显示自定义字段

Posted

技术标签:

【中文标题】Wordpress 过滤多个下拉分类以通过 ajax 显示自定义字段【英文标题】:Wordpress Filter multiple drop-down taxonomies to display custom field via ajax 【发布时间】:2016-12-21 22:39:55 【问题描述】:

我目前有一个名为 newcpt 的自定义帖子类型。这有 2 个分类法,regioncity。 在地区我有regionaregionb,在城市我有cityacityb

我目前正在使用 wp_dropdown_categories 获取regiona 的下拉列表。是否有一种快速或简单的解决方案来显示第二个下拉列表,该下拉列表仅在它也有 regiona 作为分类时显示。

例如。我有一个testpost 的帖子,它在regionacitya 中,当从下拉列表中选择regiona 时,我希望第二个下拉列表填充该地区的城市,所以在这种情况下@987654335 @

一旦还选择了一个城市,它将从该cpt 中获取所有帖子,并在同一页面上使用匹配的分类法。非常感谢任何提示或有用的链接!

【问题讨论】:

你说的是前端过滤器,比如小部件或类似的,对吧?所以我访问your.site 并首先查看您的 Region-Drop-Down。选择 Region 后,我可能还会看到 city-Dropdown,对吧? 正确。因此,在位置页面上,您会看到一个下拉列表。选择下拉菜单后,第二个下拉菜单会显示过滤选项,并且带有此选项的帖子会在下方过滤。一旦出现第三个下拉菜单,它就会记录下面的实际帖子 好的,您可以通过 php 在服务器端或通过 javascript 在客户端执行此操作。如果您想依赖 php 和 wp_dropdown_categories,最好在每次更改下拉菜单时重新加载页面。因此,您可以使用所选区域的信息在服务器端构建第二个下拉菜单。你知道我的意思吗? 有没有办法确保页面没有重新加载,重要的是页面加载,然后用户将永远不会看到刷新。有没有其他办法解决这个问题 使用较少的 Javascript 和一些 PHP,您将生成大量 html。这可不是什么好主意。我认为最好的方法是留下``` wp_dropdown_categories ```并通过PHP生成带有所有信息的JSON-Object,然后使用JavaScript / AngularJS在浏览器中呈现下拉菜单。 【参考方案1】:

很难弄清楚你现实世界的问题,但我会尽力而为:

让我想象一下您要归档的内容

jQuery(document).ready(function($)
  "use strict";
  var parentSelectBox = $("#parent-select-box");

  parentSelectBox.change(function(e)

    e.preventDefault();

    var childForm = $("#child-select-box"), parentTermID = parentSelectBox.val();
    var terms = 
      "1": [
        id: 11, name: "Child Term 1.1",
        id: 12, name: "Child Term 1.2"
      ],
      "3": [
        id: 21, name: "Child Term 2.1",
        id: 22, name: "Child Term 2.2"
      ]
    ;

    childForm.empty(); // Remove all old options.
    childForm.append('<option disabled selected>--Select a child term--</option>');

    if (terms.hasOwnProperty(parentTermID)) 
      var childTerms = terms[parentTermID];
      $.each(childTerms, function() // Add new options.
        childForm.append('<option value="' + this.id + '">' + this.name + '</option>');
      );
     else 
      console.log('There are no child terms.');
    
  );
);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="parent-from" class="form parent" method="post">
  <select id="parent-select-box" name="parent-term">
    <option disabled selected>--Select a parent term--</option>
    <option value="1">Parent Term 1</option>
    <option value="2">Parent Term 2</option>
  </select>
</form>
<form id="child-form" class="form child" method="get">
  <select id="child-select-box" name="child-term">
    <option disabled selected>--Select a child term--</option>
    <option value="3">Default Child Term 3</option>
    <option value="4">Default Child Term 4</option>
  </select>
</form>

如您所见,在第一个选择框中选择 Parent Term 1 后,在第二个选择框中,子术语(Child Term 1.1Child Term 1.2)会自动填充。如果您选择了Parent Term 2,您将在控制台上看到There are no child terms.

但它是纯 HTML/JS,我们必须将其合并到 WordPress 中

首先,我想你知道如何使用 AJAX 在 WordPress 中检索数据。

第一个选择框是为第二个选择框检索数据的过滤器。我们将基于父选择框的.change() 事件使用AJAX:

jQuery(document).ready(function($)
  "use strict";
  var parentSelectBox = $("#parent-select-box");
  parentSelectBox.change(function(e) // .change()
    e.preventDefault();
    var parentTermID = parentSelectBox.val();
    // 
    //   Some code with AJAX to get child terms base on `parentTermID` here.
    // 
    // Now, suppose `terms` is AJAX response.
    if ($.isEmptyObject(terms))  // There're no child terms.
      // Do something...
     else 
      // Append them to the second select box.
    
  );
); 

对于第二个选择框,我不知道您文档的 DOM 结构,但我认为我们不需要 AJAX。将GET 方法与.change() 事件一起使用:

jQuery(document).ready(function($)
  "use strict";
  var childForm = $("#child-form"),
      childSelectBox = $("#child-select-box");
  childSelectBox.change(function(e)
    e.preventDefault();
    childForm.submit();
  );
);

现在,在用户选择子术语后,子表单将自动提交,并通过GET 方法将child-term 附加到URL。我们将使用此值和pre_get_posts 操作来过滤帖子结果:

add_action('pre_get_posts', function(\WP_Query $query) 
  // If you're using main query, remember to check `$query->is_main_query()` as well.
  if ( isset($_GET['child-term']) && !empty($_GET['child-term']) ) 
    $query->query_vars['tax_query'] = [
      [
        'field'    => 'term_id',
        'terms'    => absint($_GET['child-term']),
        'taxonomy' => 'city'
      ]
    ];
  
);

您可能需要查看taxonomy parameters 了解更多信息。

【讨论】:

【参考方案2】:

FacetWP 做你想做的事,但甚至可能比你所布置的更好 - 基于分类过滤器的数据集的 AJAX 更新。您将同时拥有显示地区和城市的下拉菜单,用户可以切换他们需要的内容。如果你想做依赖下拉的概念,你可以make a custom facet。

用法很简单 - 以下是如何将其与 WP_query 一起使用:

<?php
  // 1- Setup WP_query variable to get all your content
  // Logic here is descending alphabetical of all content
  // FacetWP handles granular search winnowing
  // Note the facetwp array item
  $args = array(
    'posts_per_page' => 9999,
    'post_type' => array('new-cpt', 'work-featured'),
    'orderby' => 'rand',
    'facetwp' => true, // so we can hook into facetwp via functions.php
  );
  $the_query = new WP_Query( $args );

  // 2- Setup new loop
  if($the_query->have_posts()) 
    while($the_query->have_posts()) :
      $the_query->the_post();
      // do your thing 
        endwhile;
  
  wp_reset_postdata();
?>

wp-admin 中设置分类后,您可以将分类过滤器直接输出到您的代码中(可能是边栏或任何您需要的地方):

<?php echo facetwp_display( 'facet', 'region' ); ?>
<?php echo facetwp_display( 'facet', 'cities' ); ?>

另一个注意事项 - 由于您使用的是自定义帖子类型,因此您必须 add a custom filter to your functions.php file:

// Adding in custom filter for FacetWP to detect custom WP_Query on facet page
function my_facetwp_is_main_query( $is_main_query, $query ) 
    if ( isset( $query->query_vars['facetwp'] ) ) 
        $is_main_query = true;
    
    return $is_main_query;

add_filter( 'facetwp_is_main_query', 'my_facetwp_is_main_query', 10, 2 );

【讨论】:

在我支付那 79 美元之前,我会使用我的 JavaScript 解决方案 -.- 可能在更大的用例中,这个插件会变得非常方便,但对于那个小任务,我认为它不值得它 我听到了,但我的收费是 125 美元/小时 - 这个插件为我解决了大约一天的工作,很容易物有所值,但 YMMV。【参考方案3】:

我认为最好的解决方案是使用 PHP 生成数据集并使用例如 AngularJS 在客户端站点上显示。

JavaScript

angular
.module('app', [])
.controller('controller', [
  '$scope',
  '$attrs',
  function ($scope, $attrs) 
    $scope.data=JSON.parse($attrs.selects);
    $scope.region = ;
    $scope.city = ;

    $scope.loadCitys = function () 
      $scope.region = JSON.parse($scope.region);
    ;

    $scope.loadPosts = function () 
      $scope.city = JSON.parse($scope.city);
    ;
  
]);

和 HTML

<!DOCTYPE html>
<html ng-app="app">

  <head>
    <script src="https://code.angularjs.org/1.5.8/angular.js"></script>
    <link rel="stylesheet" href="style.css" />
  </head>

  <body ng-controller="controller" data-selects='["name":"Region 1","citys":["name":"City 1","posts":["title":"Post 1","id":1,"title":"Post 2","id":2]],"name":"Region 2","citys":["name":"City 2","posts":["title":"Post 3","id":3,"title":"Post 4","id":4],"name":"City 3","posts":["title":"Post 5","id":5,"title":"Post 6","id":6]]]'>
    <div>
      Region: region.name <br>
      City: city.name
    </div>

    <select ng-model="region" ng-change="loadCitys()">
      <option ng-repeat="tregion in data" value="tregion">tregion.name</option>
    </select>

    <select ng-model="city" ng-change="loadPosts()">
      <option ng-repeat="tcity in region.citys" value="tcity">tcity.name</option>
    </select>

    <select ng-model="post">
      <option ng-repeat="tpost in city.posts" value="tpost">tpost.title</option>
    </select>

    <script src="script.js"></script>
  </body>

</html>

活生生的例子:https://plnkr.co/edit/gyzCxMpn9luAcGsLZHYD

(你必须完成它)

【讨论】:

这是一个荒谬的答案——他要求基于 WordPress 的解决方案。 您不能合法地要求此人删除 WordPress 的整个主题层并用 WP-API 和 Angular 替换它。这不是一个明智的解决方案。

以上是关于Wordpress 过滤多个下拉分类以通过 ajax 显示自定义字段的主要内容,如果未能解决你的问题,请参考以下文章

使用 Ajax 的带有自定义分类法的 Wordpress 多个自定义帖子类型过滤器 - 所有新创建的帖子都不会在响应中显示

php WordPress |类别过滤器下拉列表

使用下拉菜单动态过滤 Wordpress 帖子(使用 php 和 ajax)

在 wordpress 中应用搜索过滤的插件

多个分类法的 WordPress 存档页面

在存档页面上添加下拉分类过滤器