Use selective refresh in the customizer

Since WordPress 4.5, we can reload only parts of the customizer preview after a setting has changed. With that, the user has — at least — the feeling of a faster experience. And in most cases, it will be actually faster (and besides that, this feature could eliminate the customizer page and replace it with inline editing, writes Weston Ruter in his post »Selective Refresh in the Customizer«). Here I show you how to implement selective refresh.

Using selective refresh for a customizer setting

Using the feature with an existing customizer setting is actually quite simple. Here comes a complete example for a customizer setting from my Photographus theme:

/** * Create setting for page. */ $wp_customize->add_setting( "photographus_panel_{$i}_page", [ 'default' => false, 'sanitize_callback' => 'absint', 'transport' => 'postMessage', ] ); /** * Create control for page. */ $wp_customize->add_control( "photographus_panel_{$i}_page", [ 'label' => __( 'Select page', 'photographus' ), 'section' => 'photographus_options', 'type' => 'dropdown-pages', 'allow_addition' => true, 'active_callback' => 'photographus_is_page_panel', 'input_attrs' => [ 'data-panel-number' => $i, ], ] ); $wp_customize->selective_refresh->add_partial( "photographus_panel_{$i}_page_partial", [ 'selector' => "#frontpage-section-$i", 'settings' => [ "photographus_panel_{$i}_page", ], 'render_callback' => 'photographus_the_page_panel', 'container_inclusive' => true, ] );
Code language: PHP (php)

The add_setting() and add_control() part should not be something new for you if you already worked with the customizer. Since 4.5 we can use $wp_customize->selective_refresh->add_partial, which we hand over a unique identifier as the first param and a settings array as the second, which contains the following values:

  • An HTML selector, who specifies the element which needs a reload.
  • One or more settings, which trigger the refresh.
  • A callback function which echoes the new markup.
  • The instruction to also reload the container element in our case (#frontpage-section-$i).

And that is it — we implemented selective refresh for a setting ? But there is one thing to notice:

Markup which is modified by JavaScript inside render_callback

If you reload an element which contains markup, which is modified by JavaScript (for example, a masonry grid), then you have to run the JavaScript on a selective refresh. The handling looks as following in my Photographus theme:

/** * Custom JavaScript functions for the customizer preview. * * @version 1.0.0 * * @package Photographus */ ;(function () { document.addEventListener('DOMContentLoaded', function () { /** * Selectice refresh check from https://github.com/xwp/wp-jetpack/blob/feature/selective-refresh-widget-support/modules/widgets/contact-info/contact-info-map.js#L35 * @type {*} */ hasSelectiveRefresh = ( 'undefined' !== typeof wp && wp.customize && wp.customize.selectiveRefresh && wp.customize.widgetsPreview && wp.customize.widgetsPreview.WidgetPartial ); if (hasSelectiveRefresh) { wp.customize.selectiveRefresh.bind('partial-content-rendered', function (placement) { buildMasonryGrid(hasSelectiveRefresh); addClassToImageLinks(); fullWidthImages(); /** * Get the front page panels. * @type {NodeList} */ var panels = document.querySelectorAll('.frontpage-section'); /** * Check if we have panels. */ if (0 !== panels.length) { var panelsWithContent = 0; /** * Loop through them. */ for (var i = 0; i < panels.length; i++) { /** * Check if it is a panel placeholder. */ if (!panels[i].classList.contains('frontpage-section-placeholder')) { panelsWithContent++; } } /** * Refresh the preview if we have only panel placeholders, so the default homepage is displayed * correctly. * * @link https://make.xwp.co/2015/12/08/implementing-selective-refresh-in-the-customizer/ */ if (panelsWithContent === 0) { wp.customize.preview.send('refresh'); } } }); } }); })();
Code language: PHP (php)

The important part is the first section up to line 22 — after that, you can call the functions to get the wanted behavior for the reloaded markup.

3 reactions on »Use selective refresh in the customizer«

  1. >A callback function which echoes the new markup.

    Do you know how to to use the preview value of a setting in the callback? the DB option is only updated when the customizer changes are published, so get_option() is not accurate in the callback. how do you get the preview setting value?

    1. Hi Kathy,

      it is a while since I worked with that, so I can only guess based on the code of the theme (https://github.com/florianbrinkmann/photographus/blob/9dc7296cb720a230f2fe1e8a19e7fe16f5503ea5/inc/front-page-panel-functions.php#L346). It seems that the callback function gets an object as the first parameter that includes the panel number. And with that, I can use get_theme_mod() to get the new value (Weston writes in his comment to the announcement post that you will get the new value there in the Customizer context).

      Hope that helps!

      Best,
      Florian

      1. Thanks so much Florian! I have been digging around in the customizer source and it looks like it is meant to filter the option via the pre_option_$option_name when in preview mode. ... which is inline with what Weston writes there. I must have something else going wrong...

Leave a Reply

Your email address will not be published. Required fields are marked *