Support

Account

Home Forums Backend Issues (wp-admin) Populate Text Fields on Select Field Change

Solving

Populate Text Fields on Select Field Change

  • Hello,
    I am fairly familiar with ACF — on the front-end. But I have not yet done much customization on the back-end. I have a nested repeater (so, repeater in a repeater) that has a Taxonomy field that uses the Select display.

    There are 8 text fields that follow this nested repeater. What I would like to happen is that, if you select an option from the Taxonomy field, the 8 text fields are populated with data from the selected Taxonomy item (which has custom fields of its own).

    Thus far I’ve figured out how to enqueue admin scripts, in my admin JS file target the change() event on the Taxonomy field’s select with jQuery, and spit out the selected value. But I’m not exactly sure where to go from here.

    This is the closest example I’ve seen to what I’d like to do: https://github.com/Hube2/acf-dynamic-ajax-select-example/tree/master/dynamic-text-based-on-user-select

    But I’m a little foggy on even how and where I am to begin with this. Do I create a plugin out of these files? Or do I load them from my functions.php? Or?

    Thanks for the help.

  • Hi, that’s one of my examples.

    You don’t need to create a plugin, you can add the code directly.

    Basically there are 3 parts. There is the addition of the custom JavaScript file done on the acf/input/admin_enqueue_scripts hook. This goes in your functions php file.

    The second part is the custom JavaScript file that does the work of making the request and populating fields.

    Then there is the PHP side of the AJAX request, this also goes into your functions.php file. My example is built as a class, just because I use OOP for just about everything.

    The main difference here is that you need to know what row of the repeater you are on. You can get the row by using

    
    var $row = e.$el.closest('.acf-row');
    

    from there you can do a find to get each of the fields in the row

    
    // this will depend on what type of field you're getting
    var $field = $row.find('[data-key="field_xyz"] input');
    

    Hope that is of some help.

  • I thought I would share this. I have a client site that I’m currently working on that needs this functionality for both a set of fields as described in the other example and for a repeater field. In my case I’m loading data from the same types of fields. I have a post object field and when it changes I am loading a textarea field used for the excerpt and an image field. In one case I am also loading a text field from the post title. Because of this I am able to combine the PHP side of both AJAX requests into a single PHP function. Here is the code I am using.

    
    // PHP
    
    new client_name_mods();
    
    class client_name_mods {
        
      public function __construct() {
        add_action('acf/input/admin_enqueue_scripts', array($this, 'acf_enqueue_script'));
        add_action('wp_ajax_cm_load_relationship_content', array($this, 'get_related_content_data'));
      } // end public function __construct
      
      public function acf_enqueue_script() {
        
        $post_id = 0;
        global $post;
        if ($post && isset($post->ID)) {
          $post_id = $post->ID;
          if (get_post_type($post_id) == 'acf-field-group') {
            // do not load on field group edit page
            return;
          }
        }
        
        $handle = 'client-name-acf-extension';
        $src = '/'.str_replace(ABSPATH, '', dirname(__FILE__)).'/js/client-name-acf-extension.js';
        $depends = array('acf-input');
        wp_register_script($handle, $src, $depends);
        $object = 'client_name_acf_extension_object';
        $data = array('post_id' => $post->ID);
        wp_localize_script($handle, $object, $data);
        wp_enqueue_script($handle);
      } // end public function enqueue_script
      
      public function get_related_content_data() {
        
        if (!wp_verify_nonce($_POST['nonce'], 'acf_nonce')) {
          echo json_encode(false);
          exit;
        }
        
        $check_fields = array(
          'post_id',
          'related_post',
          'image_size',
          'field_key',
          'image_field',
          'title_field',
          'excerpt_field'
        );
        
        foreach ($check_fields as $index) {
          if (!isset($_POST[$index])) {
            echo json_encode(false);
            exit;
          }
        }
        
        $title = '';
        $excerpt = '';
        $image_id = 0;
        
        $post_id = intval($_POST['post_id']);
        $related_post = intval($_POST['related_post']);
        $image_size = $_POST['image_size'];
        $field_key = $_POST['field_key'];
        $post_object_field = $_POST['post_object_field'];
        $image_field = $_POST['image_field'];
        $title_field = $_POST['title_field'];
        $excerpt_field = $_POST['excerpt_field'];
        
        // get the current values
        $field_object = acf_get_field($field_key);
        if ($field_object['type'] == 'repeater') {
          // look for a row that already has this relationhip
          $repeater = $field['name'];
          if ($title_field) {
            $title_field = acf_get_field($title_field);
            $title_field = $title_field['name'];
          }
          $post_object_field = acf_get_field($post_object_field);
          $post_object_field = $post_object_field['name'];
          $excerpt_field = acf_get_field($excerpt_field);
          $excerpt_field = $excerpt_field['name'];
          $image_field = acf_get_field($image_field);
          $image_field = $image_field['name'];
          if (have_rows($repeater, $post_id)) {
            while (have_rows($repeater, $post_id)) {
              the_row();
              if (intval(get_sub_field($post_object_field), false) == $related_post) {
                // same related post
                if ($title_field) {
                  $title = get_sub_field($title_field, false);
                }
                $excerpt = get_sub_field($excerpt_field, false);
                $image_id = intval(get_sub_field($image_field, false));
                // found one, no reason to continue while
                break;
              } // end if already related
            } // end while rows
          } // end if rows
        } else {
          // not repeater
          $current_value = get_field($post_object_field, $post_id, false);
          if ($current_value == $related_post) {
            if ($title_field) {
              $title = get_field($title_field, $post_id, false);
            }
            $excerpt = get_field($excerpt_field, $post_id, false);
            $image_id = get_field($image_field, $post_id, false);
          }
        }
        
        if ($title == '' && $excerpt == '') {
          // net set, get values from related post
          $title = get_the_title($related_post);
          $excerpt = get_field('excerpt', $related_post, false);
          //echo json_encode(array('related_post' => $related_post)); exit;
          //echo json_encode(array('get_post_thumbnail' => true)); exit;
          $image_id = intval(get_post_thumbnail_id($related_post));
        }
        
        $image = false;
        //echo json_encode(array('image_id' => $image_id)); exit;
        if ($image_id) {
          $image_details = wp_get_attachment_image_src($image_id, $image_size);
          if ($image_details) {
            $image = array(
              'id' => $image_id,
              'url' => $image_details[0]
            );
          }
        }
        
        $array = array(
          'title' => $title,
          'excerpt' => $excerpt,
          'image' => $image
        );
        echo json_encode($array);
        exit;
        
      } // end public function get_related_content_data
      
    } // end class client_name_mods
    
    
    // JavaScript File
    
    jQuery(document).ready(function($) {
      if (typeof(acf) == 'undefined') {
        return;
      }
      var clientNameACF = acf.ajax.extend({
        events: {
          'change [data-key="field_59d246273950f"] .acf-input select': 'featured_post_change',
          'change [data-key="field_59d242a16ff63"] .acf-input select': 'related_post_change',
        }, // end events
        
        featured_post_change: function(e) {
          var $related_post = e.$el.val();
          var $post_id = client_name_acf_extension_object.post_id
          var $field_key = 'field_59d246273950f';
          var $post_object_field = 'field_59d246273950f';
          var $image_field = 'field_59d2468639510';
          var $title_field = 'field_59d246ae39511';
          var $excerpt_field = 'field_59d246bc39512';
          var $image_size = $('[data-key="'+$image_field+'"]').find('.acf-image-uploader').data('preview_size');
          var $action = 'cm_load_relationship_content';
          
          // clear current values
          $('[data-key="'+$title_field+'"] input').val('');
          $('[data-key="'+$excerpt_field+'"] textarea').val('');
          $('[data-key="'+$image_field+'"] a[data-name="remove"]').trigger('click');
          
          // if not related post is selected, return
          if (!$related_post) {
            return;
          }
          
          var self = this;
          var data = this.o;
              
          data.action = $action;
          data.related_post = $related_post;
          data.post_id = $post_id;
          data.field_key = $field_key;
          data.post_object_field = $post_object_field;
          data.image_field = $image_field;
          data.title_field = $title_field;
          data.excerpt_field = $excerpt_field;
          data.image_size = $image_size;
          
          data.exists = [];
          
          //console.log(data);
          
          this.request = $.ajax({
            url: acf.get('ajaxurl'),
            data: acf.prepare_for_ajax(data),
            type: 'post',
            dataType: 'json',
            success: function(json) {
              console.log(json);
              if (!json) {
                return;
              }
              if (json['title']) {
                $('[data-key="'+$title_field+'"] input').val(json['title']);
              }
              if (json['excerpt']) {
                $('[data-key="'+$excerpt_field+'"] textarea').val(json['excerpt']);
              }
              if (json['image']) {
                $('[data-key="'+$image_field+'"] input[type="hidden"]').val(json['image']['id']);
                $('[data-key="'+$image_field+'"] img').attr('src', json['image']['url']);
                $('[data-key="'+$image_field+'"]').find('.acf-image-uploader').addClass('has-value');
              }
            },
            error: function(jqXHR, textStatus, error) {
              console.log(jqXHR);
              console.log(textStatus);
              console.log(error);
            }
          }); // end request
          
        }, // end featured_post_chang
        
        related_post_change: function(e) {
          var $related_post = e.$el.val();
          var $post_id = client_name_acf_extension_object.post_id
          var $field_key = 'field_59d2427e6ff62';
          var $post_object_field = 'field_59d242a16ff63';
          var $image_field = 'field_59d2446e6ff64';
          var $title_field = '';
          var $excerpt_field = 'field_59d244af6ff66';
          var $action = 'cm_load_relationship_content';
          
          var $row = e.$el.closest('.acf-row');
          
          $row.find('[data-key="'+$title_field+'"] input').val('');
          $row.find('[data-key="'+$excerpt_field+'"] textarea').val('');
          $row.find('[data-key="'+$image_field+'"] a[data-name="remove"]').trigger('click');
          $image_size = $row.find('[data-key="'+$image_field+'"]').find('.acf-image-uploader').data('preview_size');
          
          // if not related post is selected, return
          if (!$related_post) {
            return;
          }
          
          var self = this;
          var data = this.o;
              
          data.action = $action;
          data.related_post = $related_post;
          data.post_id = $post_id;
          data.field_key = $field_key;
          data.post_object_field = $post_object_field;
          data.image_field = $image_field;
          data.title_field = $title_field;
          data.excerpt_field = $excerpt_field;
          data.image_size = $image_size;
          
          data.exists = [];
          
          //console.log(data);
          
          this.request = $.ajax({
            url: acf.get('ajaxurl'),
            data: acf.prepare_for_ajax(data),
            type: 'post',
            dataType: 'json',
            success: function(json) {
              console.log(json);
              if (!json) {
                return;
              }
              /*
              if (json['title']) {
                $row.find('[data-key="'+$title_field+'"] input').val(json['title']);
              }
              */
              if (json['excerpt']) {
                $row.find('[data-key="'+$excerpt_field+'"] textarea').val(json['excerpt']);
              }
              if (json['image']) {
                $row.find('[data-key="'+$image_field+'"] input[type="hidden"]').val(json['image']['id']);
                $row.find('[data-key="'+$image_field+'"] img').attr('src', json['image']['url']);
                $row.find('[data-key="'+$image_field+'"]').find('.acf-image-uploader').addClass('has-value');
              }
            },
            error: function(jqXHR, textStatus, error) {
              console.log(jqXHR);
              console.log(textStatus);
              console.log(error);
            }
          }); // end request
          
          
        }, // end related_post_change
        
      });
    });
    
  • Wow, thank you so much! I really appreciate the help. I will spend some time reviewing this.

  • the only real difference between the JS for the repeater and the JS for the non-repeater fields is that on the repeater field I added

    
    var $row = e.$el.closest('.acf-row');
    

    and then each place where I need to get or set a value for a field $row.find() is used instead of $()

    Other than this the JS code from one to the other is pretty much identical and I’ve already built in the ability to use the “title” field on the repeater because I have a good feeling that the client will want this added once the see the draft of the site I’m building for them.

    Hope it helps, there’s a bunch of extra code in there due to dealing with both a repeater and an non-repeater, but the code was just completed and tested today.

  • Hello John
    I was able to use successfully your other post :
    https://github.com/Hube2/acf-dynamic-ajax-select-example/tree/master/dynamic-fields-on-relationship

    My problem now, is to populate some fields (example: title, image …) but not from 1 post but from 2 different posts.

    I try to not use a relationship field but instead use a post object field, do you have an example with 2 objects field ?

    Concerning the example above, do you have a json field group to test with it ?

    Thank you for your help

  • You would need to have 2 different relationship or post object fields.

    If you’ve changed it to a post object field then you’ll need to figure out how to get the value of the post object field. Also, it’s been some time since I created that and even the method used for getting the value of the relationship field may have changed.

    You would need to either duplicated much of the code, especially the JS parts, or you would need to alter the JS to detect what field is being changed and populate the other fields accordingly.

    I don’t have a working example of doing this with 2 sets of fields.

  • Dear John. I would so much like to check out your script. I have some questions re. your setup. Are all the fields in one custom field group? Are there one or two post types? Is it correct that for the first part of the .js the $field_key and var $post_object_field has same value and for the other part they do not?

    featured_post
    $field_key = ‘field_59d246273950f’;
    var $post_object_field = ‘field_59d246273950f’;

    var $image_field = ‘field_59d2468639510’;
    var $title_field = ‘field_59d246ae39511’;
    var $excerpt_field = ‘field_59d246bc39512’;

    related_post
    var $field_key = ‘field_59d2427e6ff62’;
    var $post_object_field = ‘field_59d242a16ff63’;

    var $image_field = ‘field_59d2446e6ff64’;
    var $title_field = ”;
    var $excerpt_field = ‘field_59d244af6ff66’;

    My goal is to have a ”CTA” post type with standard ”call to action” sentences in 5 languages. In my main post type a have 5 repeaters. When I select a sentence in in Danish in the first, I want the translations of that sentence inserted in the corresponding fields in the 4 repeaters below. I hope I can learn the basics og getting your script going.

  • There are many post types on this site. My script will put the data from any post type. I have the standard posts and pages and in this project I also created a CPT for “products” and another for “projects” The script is designed to pull information from any post type.

    There are 2 field groups. One field group is used for setting a “featured post” and one field group is used for setting up “related posts”. These two field groups are mixed and matched on the various post types and page templates. For example on the blog the client can select only “related posts” but on a project they can also select a “featured post”, and when I say post that means of any post type.

    In this part of the script

    
    'change [data-key="field_59d246273950f"] .acf-input select': 'featured_post_change',
    'change [data-key="field_59d242a16ff63"] .acf-input select': 'related_post_change',
    

    the first field key is the field key of the post object field for the featured post. The second is the field key of the post object field that is inside the repeater used to select related posts.

    The other field keys all relate to the other fields in each of the field groups so they are all different depending on if I’m populating the fields in the repeater vs the fields that are not in the repeater.

    I’m attaching the field groups in an export if that will help.

  • Wau. Thank you John for your thorough explanation. I´ll import your field groups an start play around. All the best.

  • Hi John
    I have a really simple issue. I have an ACF field called “project_name” in my custom post type “Client.” Each client has a page /client/first-last/. I populate the field within the respective client’s page with the project’s name and then I’m trying to add that dynamically to a hidden gravity form field. I’ve tried shortcode, nothing appears. I can get it to appear in the main page itself with shortcode, but not in the GF field. I’ve tried the custom field option, the ACF field appears there, but nothing ever shows in the field itself. Thanks in advance.

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

The topic ‘Populate Text Fields on Select Field Change’ is closed to new replies.