10

I have a section in a page template in the theme I'm making that displays content based on a page the user selects in the customizer using the dropdown-pages control. Right now it's just using the standard default refresh transport, but since that's kind of clunky reloading the whole iframe, I was wondering if it was possible to use the new selective refresh feature. But I'm not sure how to implement it. Anyone know if this is possible and if so how to do it?

Here is the code in my page template that displays the content:

<?php if ((get_theme_mod( 'intro_page' )) != '') {

$intro_id = get_theme_mod( 'intro_page' );

$intro_header = get_the_title( $intro_id );

$intro_excerpt = get_the_excerpt( $intro_id );

$intro_link = get_the_permalink( $intro_id );

$intro_linktext = get_post_meta( $intro_id, 'emm_cta_text', true );

echo '<h1>' . esc_html($intro_header) . '</h1>' . '<p>' . esc_html($intro_excerpt) . '</p>';

if( ! get_post_meta( $intro_id, 'emm_cta_text', true ) ) {
echo '<p><a class="cta" href="' . esc_url($intro_link) . '">Learn More</a></p>';
}else{
echo '<p><a class="cta" href="' . esc_url($intro_link) . '">' . esc_html($intro_linktext) . '</a></p>';
}
} ?>

Here is the code for the setting in customizer:

$wp_customize->add_setting( 'intro_page' , array(
'sanitize_callback' => 'absint',
) );

$wp_customize->add_control( 'intro_page', array(
'label'    => __( 'Page to use for intro section', 'veritas' ), 
'section'  => 'intro',
'settings' => 'intro_page',
'type'     => 'dropdown-pages',
'priority' => 1
) );
10

Create a function to output the selectively refreshed template code

(I wrapped the HTML within <div class="cta-wrap"> to make it easier to target this particular block of markup.)

function wpse247234_cta_block() {
    if ( ( get_theme_mod( 'intro_page' ) ) != '' ) {
        $intro_id       = get_theme_mod( 'intro_page' );
        $intro_header   = get_the_title( $intro_id );
        $intro_excerpt  = get_the_excerpt( $intro_id );
        $intro_link     = get_the_permalink( $intro_id );
        $intro_linktext = get_post_meta( $intro_id, 'emm_cta_text', true );

        echo '<div class="cta-wrap">';
            echo '<h1>' . esc_html( $intro_header ) . '</h1>' . '<p>' . esc_html( $intro_excerpt ) . '</p>';

            if ( ! get_post_meta( $intro_id, 'emm_cta_text', true ) ) {
                echo '<p><a class="cta" href="' . esc_url( $intro_link ) . '">Learn More</a></p>';
            } else {
                echo '<p><a class="cta" href="' . esc_url( $intro_link ) . '">' . esc_html( $intro_linktext ) . '</a></p>';
            }
        echo '</div>';
    }
}

Update your template with a call to the newly created function above:

wpse247234_cta_block();

Set up the Customizer

function wpse247234_customize_register( $wp_customize ) {

    $wp_customize->add_section( 'intro', array (
            'title'    => __( 'intro', 'text-domain' ),
            'priority' => 999,
    ) );

    $wp_customize->add_setting( 'intro_page' , array(
            'sanitize_callback' => 'absint',
            'transport' => 'postMessage'
    ) );

    $wp_customize->add_control( 'intro_page', array(
            'label'    => __( 'Page to use for intro section', 'text-domain' ), 
            'section'  => 'intro',
            'settings' => 'intro_page',
            'type'     => 'dropdown-pages',
            'priority' => 1
    ) );

    $wp_customize->selective_refresh->add_partial( 'intro_page', array(
        'selector'            => '.cta-wrap',
        'container_inclusive' => true,
        'render_callback'     => 'wpse247234_cta_block',
        'fallback_refresh'    => false, // Prevents refresh loop when document does not contain .cta-wrap selector. This should be fixed in WP 4.7.
    ) );
}
add_action( 'customize_register', 'wpse247234_customize_register' );

Styling the item as it's being refreshed

While the partial is refreshing, the affected element will have the class customize-partial-refreshing added to it. You can style it like so:

.cta-wrap.customize-partial-refreshing {
    // styles...
}

Helpful links

  • seems like you know too much ;) so if you think you might have an answer the next level is to have a mixed settings with some attribute change triggering partial refresh while others full refresh (full in this case is needed to set global JS options). Should I make a formal question? ;)) – Mark Kaplun Nov 24 '16 at 6:38
  • @MarkKaplun, if you knew how long this answer took me it wouldn't seem that way at all :-) In my testing setup, I have a mixture of full page refresh options in addition the selective refresh above. Seems to work fine right out of the box. If you don't mind I would prefer a new question with your specific details, and when time allows, I'd be happy to take a crack at it. – Dave Romsey Nov 24 '16 at 6:47
  • 1
    Regarding the fallback_refresh comment: “prevents constant refresh when document does not contain .cta-wrap selector”. The bug with infinite reloading should be fixed in 4.7-RC1. – Weston Ruter Nov 24 '16 at 7:12
  • 1
    @dave-romsey What's the point of the JS in customize-preview.js? It looks like it is setting the element's content to the page ID? Shouldn't selective refresh be handling all of this for you instead and so there is no need for this JS file at all? – Weston Ruter Nov 24 '16 at 7:37
  • @WestonRuter thank you for the note about the fix for the infinite refresh in 4.7-RC1. You are right (naturally :-p ) about the customize-preview.js being unnecessary too, so I've removed it from the answer. – Dave Romsey Nov 24 '16 at 7:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.