How to make get_theme_mod work with AJAX in the customizer preview

Is it possible to make the get_theme_mod work after refresh in the customizer preview pane when it's being called inside a template part by AJAX?

I have a theme that loads the posts on scroll (infinite scroll) and everything works except it doesn't output the updated theme mods in the customizer preview. It only outputs the new theme mods when I hit the save button.

Any idea how to make it update after a refresh as well?

My control settings:


'id'        => 'show_caption',
'type'      => 'select',
'section'   => 'caption',
'transport' => 'refresh',
'default'   => 'top',
'choices'   => array(
  'top'    => __( 'Top', 'my-domain' ),
  'bottom' => __( 'Bottom', 'my-domain' ),
),

InfiniteScroll.php:


class InfiniteScroll {

  private $query;

  public function __construct( WP_Query $query ) {
    $this->query = $query;
  }
  
  public function register() {
    add_action( 'wp_ajax_my_infinite_scroll', array( $this, 'handleAjax' ) );
    add_action( 'wp_ajax_nopriv_my_infinite_scroll', array( $this, 'handleAjax' ) );
    add_action( 'wp_enqueue_scripts', array( $this, 'enqueueScripts' ) );
  }

  public function getPosts() {
    ob_start();

    $this->query->query( $this->getData() );

    if ( $this->query->have_posts() ) {
      while ( $this->query->have_posts() ) {
        $this->query->the_post();
        get_template_part( 'template-parts/post/content' );
      }
    }

    wp_reset_postdata();

    return ob_get_clean();
  }

  public function handleAjax() {
    if ( ! check_ajax_referer( 'infinite-scroll-ajax', 'nonce' ) ) {
      wp_die();
    }

    wp_send_json_success( $this->getPosts() );

    wp_die();
  }
  
  // ...

}

content.php:


echo get_theme_mod( 'show_caption', 'top' );

Ajax request before customize_save:

Topic theme-customizer get-theme-mod get-template-part ajax options Wordpress

Category Web


There is a bug in WordPress 4.8.2 which causes pending customized changes to not be injected into Ajax requests in the preview. This has been fixed in 4.9-alpha via #42162. In the mean time, however, you can do a workaround to modify the requested url with logic like:

// Workaround defect introduced in WordPress 4.8.2 where preview nonce is not included in request.
if ( 'undefined' !== typeof _wpCustomizeSettings ) {
    urlParser = document.createElement( 'a' );
    urlParser.href = url;
    urlParser.search += '&customize_preview_nonce=' + _wpCustomizeSettings.nonce.preview;
    url = urlParser.href;
}

About

Geeks Mental is a community that publishes articles and tutorials about Web, Android, Data Science, new techniques and Linux security.