Populating autocomplete field with custom post type

Your question is quite complicated, but lets give it a shot!

I recently made a class that does just that that I am happy to share.

It isn’t a complete response but will get you most of the way there.

What you need to know is the quirky way WP does ajax, which involves registering an action at the WordPress ajax endpoint.

class YOURCPT_autocomplete {

  /**
  * Constructor
  */
  public function __construct() {
    // add actions on construct
    add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ), 5 );

    // And these two actions are the ajax search actions
    // we use the hook wp_ajax_{action} to define our ajax action
    // here we defined the 'search' action
    // for both logged in and out users
    // in your case you probably dont need the 'nopriv' hook, for logged out users
    add_action( 'wp_ajax_search', array( $this, 'ajax_search' ) );
    add_action( 'wp_ajax_nopriv_search', array( $this, 'ajax_search' ) );

    // in all of the cases above we call a method of this same class:
    // array( $this, 'your_function_name' );
  }

  /**
  * Register scripts
  */
  public function enqueue_scripts() {

    // enqueue JS and CSS. 
    // You will have to change these next two lines to point to your own
    wp_enqueue_style( 'autocomplete', YOURTHEME_OR_PLUGIN_BASE . '/YOUR.css' );
    wp_enqueue_script( 'autocomplete', YOURTHEME_OR_PLUGIN_BASE . '/js/YOUR.js', array( 'jquery-ui-autocomplete' ), 'true', true );

    // then we get a reference to the ajax endpoint using wp_localize script
    // this will create a variable called `opts` which has a member
    // `ajax_url` which, you guessed, has the ajax url.
    wp_localize_script( 'autocomplete', 'opts', array(
      'ajax_url' => admin_url( 'admin-ajax.php' ) )
    );
  }

  /**
  * Ajax - this is the function that searches CPTs
  */
  public function ajax_search() {
    // we send ajax request to ajax_url

    // check for term, if doesnt exist die
    if ( empty( $_REQUEST['term'] ) ) {
        wp_die();
    }

    // WP Query arguments
    // we get the 'term' from the ajax call, clean it and make a search
    $args = array(
      's'         => trim( esc_attr( strip_tags( $_REQUEST['term'] ) ) ),
      'post_type' => 'YOURCPT'
    );

    // array to keep results
    $results = array();

    // make a query 
    $query = new WP_Query( $args );

    // save results
    // formatted with the title as 'label' for the autocomplete script 
    if ( $query->have_posts() ) {
        while ( $query->have_posts() ) {
          $query->the_post();
          $results[] = array(
              'label'     => esc_html( get_the_title() ),    // title
              'link'      => get_permalink(),                // link
              'id'        => get_the_ID(),                   // id
               // and whatever eles you want to send to the front end
          );
        }
    }

    // echo results
    echo json_encode($results);

    // kill process
    // all ajax actions in WP need to die when they are done!
    wp_die();
  }

}

Next is the JS (will skip the css)

jQuery( function ($) {

  // create an jq-ui autocomplete on your selected element
  $( 'WHICHEVER_ELEMENT_WILL_USE_AUTOCOMPLETE' ).autocomplete( {
    // use a function for its source, which will return ajax response
    source: function(request, response){

      // well use opts.ajax_url which we enqueued with WP
      $.post( opts.ajax_url, {
            action: 'search',            // our action is called search
            term: request.term           // and we get the term com jq-ui
        }, function(data) {
          // when we get data from ajax, we pass it onto jq-ui autocomplete
          response(data);
        }, 'json'
      );
    },
    // next, is the select behaviour
    // on select do your action
    select: function(evt, ui) {
      evt.preventDefault();

      // here you can call another AJAX action to save the option
      // or whatever

    },
  } );
} ( jQuery ) );

Cool! Now just create the class in your funcitons.php which will enqueue everything for you.

// include the file where you have your class, if not in your functions.php
include( 'path/to/the/class/YOURCPT_autocomplete.php' );

// instantiate the class
new YOURCPT_autocomplete();

Done!

You could do this last step conditionally, and only include it in certain pages, posts types, etc.

To save the selected option you could create another ajax action, using the hooks like on the class above.

Your handling function could use update_user_meta with the terms

Finally, to use multiple values, you should have a look at the jQuery ui docs. You can definitely do it: https://jqueryui.com/resources/demos/autocomplete/multiple.html

I will definitely recommend smashingmag if you want good tutorials on these fiddly wordpress features: https://www.smashingmagazine.com/2011/10/how-to-use-ajax-in-wordpress/

Hope that gets you started well!