简体   繁体   English

高级自定义字段/根据另一个 acf 字段填充选择

[英]Advanced custom fields / populate select based on another acf field

regarding advanced custom fields repeater and select drop downs.关于高级自定义字段转发器和选择下拉列表。 i currently have a website which revolves around cars.我目前有一个围绕汽车的网站。

In an options page in wordpress, i have a repeater block with one text field named 'manufacturer' and another called 'models' as a text area field.在 wordpress 的选项页面中,我有一个转发器块,其中一个文本字段名为“制造商”,另一个名为“模型”作为文本区域字段。

the text area is populated on each line with a model, so on one row for example:文本区域在每一行上填充一个模型,例如在一行中:

manufacturer = audi models = A1 A2 A3 A4 etc..制造商 = 奥迪车型 = A1 A2 A3 A4 等。

on the custom post type 'lease' for the cars i have made 2 select drop downs for manufacturer and models.在汽车的自定义帖子类型“租赁”上,我为制造商和型号做了 2 个选择下拉列表。

I can auto-populate the manufacturer as per the example #2 code here:我可以根据此处的示例 #2 代码自动填充制造商:

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

that works fine no problem!没问题!

then with the models drop down select, ONLY when the manufacturer select drop down changes to then auto populate it with the models from the repeater on the options page showing only the models based on the manufacturer...然后使用模型下拉选择,仅当制造商选择下拉更改为然后使用选项页面上的中继器中的模型自动填充它时,仅显示基于制造商的模型...

Im aware this requires ajax to do so..我知道这需要 ajax 这样做..

I have a sample code that i was testing the other week, i could get it to do what i wanted but when you go into the single car it would be blank, then when you select the options and then save/update the refreshed screen the models select drop down would be blank again, although with testing it shows that it has sent the data to the database and has saved.我有一个示例代码,我前一周正在测试,我可以让它做我想做的事情,但是当你进入单车时它会是空白的,然后当你选择选项然后保存/更新刷新的屏幕时模型选择下拉列表将再次为空白,尽管通过测试表明它已将数据发送到数据库并已保存。

so how do i fix the issue when i save the car post that it doesn't go blank?那么当我保存汽车帖子时它不会变成空白,我该如何解决这个问题?

here is the code i was testing这是我正在测试的代码

PHP 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: 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();
});

I assume it is something to do with the Javascript?我认为这与Javascript有关?

any advise or help would be appreciated,任何建议或帮助将不胜感激,

thank you in advance.先感谢您。

R电阻

I know this question is a bit old but it has a few upvotes so I thought it would be worth posting an answer for this problem.我知道这个问题有点老了,但它有一些赞成票,所以我认为值得发布这个问题的答案。

When you edit a 'lease' post, set the manufacturer then populate the model field from its value with AJAX, the models select box is populated with values for the chosen manufacturer.当您编辑“租赁”帖子时,设置制造商,然后使用 AJAX 从其值填充模型字段,模型选择框将填充所选制造商的值。 This value isn't validated server-side as a 'valid' choice, so it is saved in your database as post meta correctly.此值未在服务器端验证为“有效”选择,因此它会正确保存在您的数据库中作为 post meta。

On loading the edit screen again, the current value for model is not selected because when Advanced Custom Fields generates the HTML for a select field server-side, there are no choices to be pre-selected.再次加载编辑屏幕时,未选择模型的当前值,因为当高级自定义字段为选择字段服务器端生成 HTML 时,没有要预先选择的选项。 The following PHP walker from fields/select.php is passed the fields $choices and $values for the field/post being edited:来自 fields/select.php 的以下 PHP walker 被传递给正在编辑的字段/帖子的字段$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>';

    }

}

As your field has no choices until AJAX uses the manufacturer field to populate them, the selected attribute isn't set.由于您的字段在 AJAX 使用制造商字段填充它们之前没有选择,因此不会设置 selected 属性。 You should populate choices for the model field server-side too to retain the value on post edit screen after saving.您也应该填充模型字段服务器端的选项,以在保存后保留后期编辑屏幕上的值。 For example:例如:

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');

This will also disable the model field on load if the manufacturer hasn't been set, I assume a new post, allowing you to remove the .change() call from your JS which is causing the manufacturer select changed event to be triggered on load too.如果制造商尚未设置,这也会在加载时禁用模型字段,我假设一个新帖子,允许您从 JS 中删除.change()调用,这会导致制造商选择更改事件在加载时触发也。 This would append duplicate model options after those passed server-side otherwise.否则,这将在通过服务器端的那些选项之后附加重复的模型选项。

You should update the JS to remove the 'old' options too on manufacturer change else if you selected a manufacturer then changed it to another, both manufacturers models would be included in the options.您应该更新 JS 以删除制造商更改时的“旧”选项,否则如果您选择了一个制造商然后将其更改为另一个制造商,则这两个制造商型号都将包含在选项中。 For example:例如:

// 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' );
  }
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM