ACF表单Post Object字段筛选:如何按选中客户显示对应项目?
实现ACF前端表单Client与Project的联动过滤
要让Task表单里的Project选择器仅显示与选中Client关联的项目,需要结合后端钩子过滤初始选项,再加前端JS实现实时联动,具体步骤如下:
1. 后端过滤Project字段的初始选项
使用ACF的acf/fields/post_object/query钩子,针对前端Task表单,根据已选中的Client过滤Project选项:
add_filter('acf/fields/post_object/query', 'filter_projects_by_selected_client', 10, 3); function filter_projects_by_selected_client($args, $field, $post_id) { // 仅对前端Task编辑/新建表单生效 if (!is_admin() && get_post_type($post_id) === 'tasks') { // 获取当前选中的Client(编辑现有Task时) $selected_client = get_field('client', $post_id); // 新建Task时,可通过URL参数?client_id=XXX预设选中的Client if (!$selected_client && isset($_GET['client_id'])) { $selected_client = absint($_GET['client_id']); } if ($selected_client) { // 过滤出关联该Client的Project(替换'client'为你Project中关联Client的ACF字段键名) $args['meta_query'] = array( array( 'key' => 'client', 'value' => $selected_client, 'compare' => '=' ) ); } } return $args; }
2. 前端JS实现实时联动
当用户切换Client下拉框时,通过AJAX动态更新Project选项:
第一步:注册并加载自定义JS
在主题functions.php中添加:
add_action('acf/input/admin_enqueue_scripts', 'enqueue_task_form_scripts'); function enqueue_task_form_scripts() { // 仅在前端Task表单页面加载脚本 if (!is_admin() && get_post_type() === 'tasks') { wp_enqueue_script('task-form-script', get_template_directory_uri() . '/js/task-form.js', array('jquery', 'acf-input'), '1.0', true); // 传递AJAX所需参数 wp_localize_script('task-form-script', 'taskFormAjax', array( 'ajaxUrl' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('task_form_nonce') )); } }
第二步:编写联动逻辑JS
在主题目录下创建js/task-form.js,写入:
jQuery(document).ready(function($) { // 监听Client字段变化 $('#acf-field-client').on('change', function() { const clientId = $(this).val(); const projectField = $('#acf-field-project'); // 清空现有选项 projectField.empty(); if (!clientId) { projectField.append('<option value="">请先选择客户</option>'); return; } // AJAX请求获取关联项目 $.ajax({ url: taskFormAjax.ajaxUrl, type: 'POST', data: { action: 'get_projects_by_client', client_id: clientId, nonce: taskFormAjax.nonce }, success: function(response) { projectField.append('<option value="">选择项目</option>'); if (response.success) { $.each(response.data, function(id, title) { projectField.append(`<option value="${id}">${title}</option>`); }); } else { projectField.append('<option value="">无关联项目</option>'); } }, error: function() { projectField.append('<option value="">加载失败</option>'); } }); }); // 页面加载时,若已有选中的Client,自动触发一次更新 const initialClientId = $('#acf-field-client').val(); if (initialClientId) { $('#acf-field-client').trigger('change'); } });
3. 编写AJAX回调函数
在functions.php中添加处理AJAX请求的函数:
add_action('wp_ajax_get_projects_by_client', 'get_projects_by_client'); add_action('wp_ajax_nopriv_get_projects_by_client', 'get_projects_by_client'); // 允许未登录用户访问 function get_projects_by_client() { // 验证权限 if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'task_form_nonce')) { wp_send_json_error('权限验证失败'); } $client_id = absint($_POST['client_id']); if (!$client_id) { wp_send_json_error('无效的客户ID'); } // 查询关联的Project(替换'client'为你Project中关联Client的ACF字段键名) $args = array( 'post_type' => 'projects', 'posts_per_page' => -1, 'meta_query' => array( array( 'key' => 'client', 'value' => $client_id, 'compare' => '=' ) ), 'orderby' => 'title', 'order' => 'ASC' ); $projects = get_posts($args); $project_options = []; foreach ($projects as $project) { $project_options[$project->ID] = $project->post_title; } wp_send_json_success($project_options); }
注意事项
- 替换代码中
'client'为你Project自定义文章类型里,关联Client的ACF字段的真实键名 - 确保自定义文章类型的slug与代码中的
tasks、projects、clients一致 - 新建Task时,可通过URL参数
?client_id=XXX预设选中的Client,自动加载对应的Project
内容的提问来源于stack exchange,提问作者jungalist
相关产品推荐
相关产品推荐

