Advanced custom fields / populate select based on another acf field
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. This value isn't validated server-side as a 'valid' choice, so it is saved in your database as post meta correctly.
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. The following PHP walker from fields/select.php is passed the fields $choices
and $values
for the field/post being edited:
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. 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. 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. For example:
// Get models field jQuery objectvar models = $('#acf-field_5548da7058203');// Disable while waiting for servermodels.prop('disabled', true);// Remove old model field optionsmodels.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' ); }});