WordPress Customizer, Selective Refresh and Partials for Multiple Settings

There are several good references about how to set up the Customizer to avoid refreshing the entire page with each change. There’s one here, and there’s some deeper explanation here. What’s not described much is how to map several settings to a single area of the page (called a Partial).

This tutorial will go into updating Partials that use several settings. I assume you have already done the other tutorials.

I wanted to create a Partial that covered several settings because the Customizer automatically displays a “pencil” button next to editable settings. When you click on the pencil, the Customizer displays the control that alters the Partial.

That’s fine for the logo, but I had created a settings group with several business address fields. Creating a separate Partial for each setting resulted in displaying one “pencil” button for each setting: ugly, and potentially confusing.

Partials

A Partial is chunk of HTML code that you get from the server and insert into the document. When you update a setting, the program can tell the server to save the setting, and get back a chunk of formatted HTML to insert into the page.

The first thing to know is that most of the tutorials, and most of your code, assumes a 1:1:1 mapping from the Customizer control to the Settings to the Partial.

For example, if I have a Setting called “business_identity_url”, I can create a control called “business_identity_url”, and a Partial called “business_identity_url”, and the tutorials explain how these things fit together. The rest of this tutorial assumes you have gone through these other tutorials — I’m not going to list any of the boilerplate code that surrounds the example code.

What we want is a Partial that groups more than one setting. For example, suppose I have two settings, business_identity_name and business_identity_city:

    $wp_customize->add_setting('business_identity_name', array(
        'type' => 'option',
        'capability' => 'manage_options',
        'default' => '',
        'transport' => 'postMessage',
        'sanitize_callback' => 'sanitize_text_field'
    )); 

    $wp_customize->add_setting('business_identity_city', array(
        'type' => 'option',
        'capability' => 'manage_options',
        'default' => '',
        'transport' => 'postMessage',
        'sanitize_callback' => 'sanitize_text_field'
    )); 

These are both saved as independent options in the wp_options table. We want to use partial page refreshes, so we set the transport to “postMessage”, otherwise, the entire page will refresh.

Next up, we add these to a Customizer section called business_identity.

    $wp_customize->add_control('business_identity_name', array(
        'type' => 'text',
        'priority' => 10,
        'section' => 'business_identity',
        'label' => __( 'Business Name' ),
        'input_attrs' => array(
            'placeholder' => ''
        )
    ));

    $wp_customize->add_control('business_identity_city', array(
        'type' => 'text',
        'priority' => 10,
        'section' => 'business_identity',
        'label' => __( 'City' ),
        'input_attrs' => array(
            'placeholder' => ''
        )
    ));

Then we create a Partial. Now, normally, I create the function to display the data first, but we’ll get to that in a moment. The code to set up the Partial is:

$wp_customize->selective_refresh->add_partial( 'business_address', array(
    'selector' => '.business-address',
    'settings' => array( 'business_identity_name', ' 'business_identity_city' ),
    'container_inclusive' => false,
    'render_callback' => 'get_customize_partial_business_address',
    'fallback_refresh' => false,
) );

Other tutorials aren’t getting into this, but the original blog post on Make.wordpress did. Typically, you see only one field name for “settings”, but you can specify an array. You can set “settings” to an array of all the settings that affect the Partial.

The callback to render the settings into HTML is:

function get_customize_partial_business_address() {
    $name = get_option( 'business_identity_name' );
    $city = get_option( 'business_identity_city' );
    $out = implode(", ", array($name, $city));
    return $out;
}

Note that I also use this in my template, like this:

<?php echo get_customize_partial_business_address(); ?>

My plugin doesn’t do it that way, exactly, but that’s the idea. Define the display logic in one place, and use it via the regular templates and over the REST interface.

Also, you need to identify the DOM element that will receive the Partial. I used the class name “business-address”.

<span class="business-address"><?php echo get_customize_partial_business_address(); ?></span>

By using class names, one partial can update more than one element. It’s useful if you have the business name in more than one place.

Also, there’s a question whether the partial should include the SPAN element. I didn’t do it that way, but I think it’s a valid way to proceed, especially if you re-use the code in several places, and need the HTML updated in all those places.

Finally, on the client side, you need a little Javascript glue code to inject the Partial into the page, using the identifier we specified. This code runs in Customizer page (not in the preview IFRAME).

    wp.customize('business_address', function(v) {
        v.bind( function( to ) {
            jQuery('.business-address').html( to );
        });
    });

When the settings change in the control, the customizer will post a request to the server to update the setting on the server. The server saves the value, then looks for a partial that’s affected by the setting, and if it finds one, it runs the render_callback function specified in the add_partial() method call.

The render callback returns the formatted HTML (which in our case is just plain text). This formatted HTML, along with the name of the partial, ‘business_address’, is delivered to the client. The customizer client code finds ‘business_address’ registered updater function, then calls it with the partial data. The function causes the partial to update the document.

It’s an involved round-trip, but it only takes a fraction of a second, and you barely notice that it’s interacting with the server.

Leave a Reply