Support

Account

Home Forums General Issues dependent dropdown select field

Solving

dependent dropdown select field

  • I’m trying to build a form where the user has to choose a taxonomy, I there a way to make a select box that contains only the parent taxonomies, and from there is user chooses a parent taxonomy the next selectbox gets populated with the taxonomies that are child of that parent taxonomy?

  • I know this is a fairly old topic, but I have been working on a project that has required me to create a select field that’s populated based on another select field and I did not want the user to need to save the post in the middle.

    I’m only going to cover the JavaScript that needs to be added to ACF to get this to work and I’m not going to go into all of the WP PHP side of building an AJAX action, this can be found and there’s plenty of information on it already.

    Basically, you create the first field as a select field and use documentation already available for dynamically loading the choices of the select field.

    I’m going to be honest, I’m not 100$ certain of everything in this, some of it is simply copied from the ACF code.

    
      jQuery(document).ready(function($){
        if (typeof acf == 'undefined') { return; }
        
        // extend ACF and add our own functios
        var bluntParasrch = acf.ajax.extend({
          
          // add events that will trigger our function to be called
          events: {
            // 'trigger #field_id': 'function_name'
            // the field id = '#acf-{$field_key}
            // this is the field key of the field we want to use to 
            // get values for the second select field
            'change #acf-field_56e1cf2e7ad26': 'field_56e1cf2e7ad26_change',
            'ready #acf-field_56e1cf2e7ad26': 'field_56e1cf2e7ad26_change',
          },
          
          // add the function that will be triggered
          _para_tax_change: function(e){
          
            // bail early if no ajax
            if( !acf.get('ajax') ) return;
            // abort XHR if it's already running
            if( this.request ) {
              this.request.abort();
            }
            // vars
            var self = this,
                data = this.o;
            // add action url
            // the action is the action you will call and that you'd add using
            // add_action('wp_ajax_... or wp_ajax_nopriv_...
            // in this case the action would take the value we send it, a term ID
            // and get children of that term
            data.action = 'get_sub_terms';
            
            // this is the value of the select field of the parent term
            // to get chidren of, this value will be in $_POST['value']
            data.value = e.$el.val();
            
            // if no value then abort
            if (!data.value) {
              return;
            }
            
            data.exists = [];
            this.request = $.ajax({
              url:    acf.get('ajaxurl'),  // ajax url, acf already sets this
              data:    acf.prepare_for_ajax(data), // another included acf function
              type:    'post', // posted values, look at $_POST in your php ajax action function
              dataType:  'json', // how we want the date returned
              success: function( json ){
                // get the field we want to populate
                var $select = $('.acf-field-56e2b71dde0c5 select');
                // this stores the currenlty selected value in that field
                // so that we can mark it as selected, this is important when loading
                // and exsiting post
                var $selected = $select.val();
                // clear all of the exsiting options from the field
                $select.empty();
                // rebuild the child select field
                $select.append('<option data-i="" selected="selected" value="">- Select -</option>');
                var count = json.length;
                for (i=0; i<count; i++) {
                  //alert(json[i]['value']+':'+json[i]['label']);
                  //var $option = $select.createElement('option');
                  //$option.value = json[i]['value'];
                  //$option.text = json[i]['label'];
                  var $item = '<option value="'+json[i]['value']+'"'
                  if ($selected == json[i]['value']) {
                    $item += ' selected="selected"';
                  }
                  $item += '>'+json[i]['label']+'</option>';
                  $select.append($item);
                }
              }
            }); // end ajax
          },
        });
        
        // trigger the ready action to load the field
        // this is important for existing posts
        $('#acf-field_56e1cf2e7ad26').trigger('ready');
        
      });
      
    
  • After upgrading to version ACF Pro 5.7 I am now getting JavaScript error when using the code example above.

    The error is:

    acf.ajax.extend is not a function

    I know there is now a new JavaScript API with version 5.7, but I have no idea of even where to start to figure out how to update the code to work.

    Any help would be greatly appreciated and thank you in advance.

  • I did not know that things had changed that much. This probably means that none of my code examples will work with the new version and it probably also means that some sites are going to break. I’ll have to look into it, hopefully I can figure out how to make it work, but I’m in the same situation.

  • It appears that just updating acf.ajax.extend to acf.Field.extend fixes the problem. Thanks for your quick response.

  • I’m not sure I understand the solution, can you give me an example?

    EDIT: NM, sometimes I can’t read, than you. I will do some testing

  • Crud. Well it fixed the console error, but I don’t think the code is running. Knew it wasn’t going to be that easy.

  • It looks like a lot of function and variable names have changed in the new JS. I am currently unable to do a lot of testing.

    This will effect all of the examples I’ve published in the past here https://github.com/Hube2/acf-dynamic-ajax-select-example. I have posted a notice there as well as opened a new issue.

    The first example I did, believe it or not, took a very long time. Weeks of trial and error in my spare time went into it. The rest were all built based on that model. With a completely new JS framework in ACF all of that testing will need to be redone with a lot of digging through the ACF code. The JS API documentation for ACF is far from complete as noted here https://www.advancedcustomfields.com/resources/javascript-api/#further-reading

    Anyone that can help with the task of creating working examples of this type of thing is welcome to give me a hand.

  • I had to rework my code and use some of new 5.7 JavaScript APIs. For example they changed acf.prepare_for_ajax to acf.prepareForAjax. The way the data element is constructed also need changing as well as abandoning the acf.ajax.extend methodology.

    Below is an attempt to rewrite your example using what I did as a basis. I make no guarantees that all my changes will make your example work, but they got my code back up and running. Hope it helps. I also left both the ready and change events in there in case people wanted to use e.type to branch the code based on the event type.

    jQuery(document).ready(function($){
        if (typeof acf == 'undefined') { return; }
    
          var acf_field = acf.getField('field_56e1cf2e7ad26');
    
          acf_field.on("change ready", function(e){
    
            // bail early if no ajax
            if( !acf.get('ajax') ) return;
    
            // abort XHR if it's already running
            if( this.request ) {
              this.request.abort();
            }
    
            // set the ajax action that's set up in php
            var data  =  { 
                action: 'get_sub_terms',
                key_name: acf_field.val(); //The key_name needs to be the name of the parameter in your action
            }
    
            this.request = $.ajax({
              url:    acf.get('ajaxurl'),  // ajax url, acf already sets this
              data:    acf.prepareForAjax(data), // another included acf function
              type:    'post', // posted values, look at $_POST in your php ajax action function
              dataType:  'json', // how we want the date returned
              success: function( json ){
                // get the field we want to populate
                var $select = $('.acf-field-56e2b71dde0c5 select');
                // this stores the currenlty selected value in that field
                // so that we can mark it as selected, this is important when loading
                // and exsiting post
                var $selected = $select.val();
                // clear all of the exsiting options from the field
                $select.empty();
                // rebuild the child select field
                $select.append('<option data-i="" selected="selected" value="">- Select -</option>');
                var count = json.length;
                for (i=0; i<count; i++) {
                  var $item = '<option value="'+json[i]['value']+'"'
                  if ($selected == json[i]['value']) {
                    $item += ' selected="selected"';
                  }
                  $item += '>'+json[i]['label']+'</option>';
                  $select.append($item);
                }
              }
            }); // end ajax
    
          });
    
          // trigger the ready action to load the field
          // this is important for existing posts
          $('#acf-field_56e1cf2e7ad26').trigger('ready');
        
      });
  • Thanks Joshua for sharing that! Had a similar issue and was now able to fix it quickly…

  • You’re welcome. I glad I could help.

  • joshua-stewart,
    I am trying your fix but i get an error “Uncaught SyntaxError: Unexpected token ;” on “key_name: acf_field.val();”

    Here is my .php https://pastebin.com/kYRpCreY
    Here is my .js https://pastebin.com/ABFTEzL4

    My files is the examples from John Huebner with your fix.

  • v4nelle,

    This error is likely because you need to change the key_name property to match the parameter of your load_city_field_choices function. key_name is just a placeholder I put in the example and the reason I added the comment //The key_name needs to be the name of the parameter in your action

    Hope this helps.

  • I do it ,but it doesnt work.
    Anybody who can upload the .php and .js files to compare them with mine?

  • Just a note, this may not always work.

    
    var acf_field = acf.getField('field_56e1cf2e7ad26');
    acf_field.on("change ready", function(e){
    

    The reason being that it will not work on fields that are dynamically added after the page is loaded. In one of the sites I’m working on I needed to do something like this

    
    $(document).on('change', '[data-key="field_5b6c628cb8088"] .acf-input input', function(e) {
      // ...
    });
    
  • John Huebner,
    i am trying to modify your code to support repeater field.
    I want the City Field(Poikilia in my project) and the State Field(Kalliergeia in my project) to be into repeater(name = kalliergeies, key=field_5b5e20cb6334a).

    My problem is when i am trying to put the have_rows functions into my .php file all the code freeze and i get Error 500.

    When i put the have_rows into functions.php i have not problem.

    if (have_rows(‘kalliergeies’)){
    debug_to_console(‘Have rows’); // Printn to console
    }

    why?

    https://pastebin.com/tvk069Ld

  • I see a few posts, which relate to cities being loaded conditionally.

    I have written a plugin which does exactly that, specifically for cities.
    See https://acf-city-selector.com.

Viewing 18 posts - 1 through 18 (of 18 total)

You must be logged in to reply to this topic.