高级自定义字段/基于另一个字段填充选择

Advanced custom fields / populate select based on another acf field

本文关键字:字段 另一个 填充 选择 自定义 高级      更新时间:2023-09-26

关于高级自定义字段重复器和选择下拉列表。我目前有一个围绕汽车的网站。

在wordpress的选项页面中,我有一个中继块,其中一个文本字段名为'manufacturer',另一个名为'models'作为文本区域字段。

文本区域用模型填充在每行上,因此在一行上,例如:

制造商=奥迪models = A1A2A3A4等

在汽车的自定义post类型'lease'上,我为制造商和型号做了2个选择下拉列表。

我可以按照示例#2代码自动填充制造商:

http://www.advancedcustomfields.com/resources/dynamically-populate-a-select-fields-choices/

可以正常工作,没有问题!

然后用模型下拉选择,只有当制造商选择下拉更改时,然后自动填充来自重复器的模型,在选项页面上仅显示基于制造商的模型…

我知道这需要ajax这样做。

我有一个示例代码,我是测试另一个星期,我可以让它做我想做的事,但当你进入单车它将是空白的,然后当你选择的选项,然后保存/更新刷新的屏幕模型选择下拉框将再次为空白,虽然测试它显示它已发送数据到数据库,并已保存。

所以我如何解决问题,当我保存汽车张贴,它不去空白?

下面是我测试的代码

PHP

function acf_admin_enqueue( $hook ) {
$type = get_post_type(); // Check current post type
$types = array( 'lease' ); // Allowed post types
if( !in_array( $type, $types ) )
  return; // Only applies to post types in array
 wp_enqueue_script( 'populate-area', get_stylesheet_directory_uri() .    '/library/dist/js/acf_select.js' );
 wp_localize_script( 'populate-area', 'pa_vars', array(
    'pa_nonce' => wp_create_nonce( 'pa_nonce' ), // Create nonce which we    later will use to verify AJAX request
  )
  );
}
add_action( 'admin_enqueue_scripts', 'acf_admin_enqueue' );
// Return models by manufacturer
function model_by_manufacturer( $selected_manufacturer ) {
// Verify nonce
if( !isset( $_POST['pa_nonce'] ) || !wp_verify_nonce( $_POST['pa_nonce'], 'pa_nonce' ) )
die('Permission denied');
// Get manufacturer var
$selected_manufacturer = $_POST['manufacturer'];
// Get field from options page
$manufacturer_and_models = get_field('car_m_and_m', 'options');
// Simplify array to look like: manufacturer => models
  foreach ($manufacturer_and_models as $key => $value) {
    $manufacturer[$value['manufacturer']] = $value['models'];
  }
  // Returns model by manufacturer selected if selected manufacturer exists in array
  if (array_key_exists( $selected_manufacturer, $manufacturer)) {
  // Convert model to array
  $arr_data = explode( ', ', $manufacturer[$selected_manufacturer] );
return wp_send_json($arr_data);
} else {
$arr_data = array();
return wp_send_json($arr_data);
}
die();
}
add_action('wp_ajax_pa_add_areas', 'model_by_manufacturer');
add_action('wp_ajax_nopriv_pa_add_areas', 'model_by_manufacturer');
Javascript:

jQuery(document).ready(function($) {
/* Add default 'Select one'
$( '#acf-field_5548d019b55cb' ).prepend( $('<option></option>').val('0').html('Select Manufacturer').attr({ selected: 'selected', disabled: 'disabled'}) );
*/
/**
 * Get manufacturer option on select menu change
 *
 */
$( '#acf-field_5548d019b55cb' ).change(function () {
    var selected_manufacturer = ''; // Selected value
    // Get selected value
    $( '#acf-field_5548d019b55cb option:selected' ).each(function() {
        selected_manufacturer += $( this ).text();
    });
    $( '#acf-field_5548da7058203' ).attr( 'disabled', 'disabled' );
    // If default is not selected get models for selected manufacturer
    if( selected_manufacturer !== 'Select Manufacturer' ) {
        // Send AJAX request
        data = {
            action: 'pa_add_areas',
            pa_nonce: pa_vars.pa_nonce,
            manufacturer: selected_manufacturer,
        };
        // Get response and populate models select field
        $.post( ajaxurl, data, function(response) {
            if( response ){
                /* Disable 'Select model' field until country is selected
                $( '#acf-field_5548da7058203' ).html( $('<option></option>').val('0').html('Select Model').attr({ selected: 'selected', disabled: 'disabled'}) );
                */
                // Add models to select field options
                $.each(response, function(val, text) {
                    $( '#acf-field_5548da7058203' ).append( $('<option></option>').val(text).html(text) );
                });
                // Enable 'Select Model' field
                $( '#acf-field_5548da7058203' ).removeAttr( 'disabled' );
            }
        });
    }
}).change();
});

我认为这是与Javascript有关?

任何建议或帮助将不胜感激,

提前谢谢你。

R

我知道这个问题有点老了,但是它有一些好评,所以我认为这将是值得发布这个问题的答案。

当您编辑'lease' post时,设置制造商,然后使用AJAX从其值填充模型字段,模型选择框将使用所选制造商的值填充。此值不会在服务器端作为"有效"选择进行验证,因此它被正确地保存在数据库中作为post meta。

再次加载编辑屏幕时,没有选择model的当前值,因为当Advanced Custom Fields为服务器端选择字段生成HTML时,没有可预选的选项。下面的PHP walker从fields/select.php中获取被编辑字段/post的$choices$values字段:

function walk( $choices, $values ) {
    // bail ealry if no choices
    if( empty($choices) ) return;

    // loop
    foreach( $choices as $k => $v ) {
        // optgroup
        if( is_array($v) ){
            // optgroup
            echo '<optgroup label="' . esc_attr($k) . '">';

            // walk
            $this->walk( $v, $values );

            // close optgroup
            echo '</optgroup>';

            // break
            continue;
        }

        // vars
        $search = html_entity_decode($k);
        $pos = array_search($search, $values);
        $atts = array( 'value' => $k );

        // validate selected
        if( $pos !== false ) {
            $atts['selected'] = 'selected';
            $atts['data-i'] = $pos;
        }

        // option
        echo '<option ' . acf_esc_attr($atts) . '>' . $v . '</option>';
    }
}

由于字段没有选择,直到AJAX使用制造商字段填充它们,因此没有设置所选属性。您也应该为模型字段的服务器端填充选项,以便保存后在编辑后的屏幕上保留该值。例如:

function load_current_models($field){
  /** Get posts current manufacturer */
  $current_manufact = get_field('manufacturer');
  /** Manufacturer must be set */
  if($current_manufact) {
    /** Get manufacturers and models from options page */
    $all_models = get_field('car_m_and_m', 'options');
    /** Look for manufacturers models **/
    foreach($all_models as $manufacturer){
      if($manufacturer['manufacturer'] == $current_manufact){
        $field['choices'] = explode(', ', $model['models']);
        return $field;
      } 
    }
  }
  /** Disable models by default */
  $field['disabled'] = true;
  return $field;
}
add_filter('acf/load_field/key=field_5548da7058203', 'load_current_models');

如果制造商尚未设置,这也将禁用加载上的模型字段,我假设有一个新的帖子,允许您从JS中删除.change()调用,这导致制造商选择更改的事件也在加载上触发。否则,将在传递给服务器端的那些模型选项之后附加重复的模型选项。

你应该更新JS,在制造商更改时也删除'旧'选项,否则如果你选择了一个制造商,然后将其更改为另一个,两个制造商型号都将包含在选项中。例如:

// Get models field jQuery object
var models = $('#acf-field_5548da7058203');
// Disable while waiting for server
models.prop('disabled', true);
// Remove old model field options
models.find('option').each(function(){
  if($(this).val() != 0) $(this).remove();
});
// Get response and populate models select field
$.post( ajaxurl, data, function(response) {
  if( response ){
    // Add models to select field options
    $.each(response, function(val, text) {
      models.append( $('<option></option>').val(text).html(text) );
    });
    // Enable 'Select Model' field
    models.removeAttr( 'disabled' );
  }
});