0

I have a custom option I've added to customizer to control the layout and allow the option to change the number of grids. Everything works properly when the option is saved and published but'm having an issue getting the live refresh part to work in customizer. :(

This is the custom option I have set up:

$wp_customize->add_section(
    'theme_options', array(
        'title'       => esc_html__( 'Theme Options ', 'testtheme' ),
        'priority'    => 250,
    )
);

$wp_customize->add_setting(
    'dynamicgrid', array(
        'default'     => 'standard-layout',
        'capability'  => 'edit_theme_options',
        'sanitize_callback' => 'testtheme_sanitize_grid_options',
    )
);

$wp_customize->add_control(
    'dynamicgrid', array(
        'settings'    => 'dynamicgrid',
        'label'       => esc_html__( 'Choose A Post Layout','testtheme' ),
        'section'     => 'theme_options',
        'type'        => 'select',
        'choices'     => array(
            'standard-layout'       => esc_html__( 'Standard Layout','testtheme' ),
            'two-grid-layout'       => esc_html__( 'Two Column Grid','testtheme' ),
            'three-grid-layout'     => esc_html__( 'Three Column Grid','testtheme' ),
            'four-grid-layout'      => esc_html__( 'Four Column Grid','testtheme' ),
        ),
    )
);

To use the refresh I call

$wp_customize->get_setting( 'dynamicgrid' )->transport       = 'postMessage';

$wp_customize->selective_refresh->add_partial(
    'dynamicgrid', array(
        'selector'          => '.posts-container',
        'settings'          => 'dynamicgrid',
        'render_callback'   => 'testtheme_customize_partial_grid_classes',
    )
);

and my render_callback is:

function testtheme_customize_partial_grid_classes( $testtheme_grid_layout ) { $grid_layout = get_option( 'dynamicgrid' ); echo $grid_layout; }

What happens when I change the option in customizer is, it does add a new class to the .posts-container but the actual preview does not update.

My grid does have masonry applied as well but I don't think thats affecting anything. If it helps, this is in my customizer.js:

wp.customize(
    'dynamicgrid', function( value ) {
        value.bind(
            function( to ) {
                if ( 'standard-layout' === to ) {
                    $( '.posts-container' ).addClass( 'standard-layout' ).removeClass( 'two-grid-layout three-grid-layout four-grid-layout' );
                } else if ( 'two-grid-layout' === to ) {
                    $( '.posts-container' ).addClass( 'two-grid-layout' ).removeClass( 'standard-layout three-grid-layout four-grid-layout' );
                } else if ( 'three-grid-layout' === to ) {
                    $( '.posts-container' ).addClass( 'three-grid-layout' ).removeClass( 'standard-layout two-grid-layout four-grid-layout' );
                } else {
                    $( '.posts-container' ).addClass( 'four-grid-layout' ).removeClass( 'standard-layout two-grid-layout three-grid-layout' );
                }
            }
        );
    }
);

And I have this in my global.js file to make sure masonry loads properly:

(function($) {
// Taken almost entirely from Baskerville. NEed to double check this...
// posts block for Masonry.
var $blocks = $( '.masonry-enabled' );

$( window ).load(
    function() {
            /**
             * Initial Masonry setup.
             */

            // Determine text direction.
            var ltr = true;
        if ( $( 'html' ).attr( 'dir' ) == 'rtl' ) {
            ltr = false;
        }

            // fire up Masonry!
            $blocks.imagesLoaded(
                function() {
                    $blocks.masonry(
                        {
                            columnWidth: 1,
                            itemSelector: '.grid-post',
                            transitionDuration: 0,
                            isOriginLeft: ltr,
                        }
                    ).masonry( 'layout' );

                    var masonryChild = $blocks.find( '.grid-post' );

                    // Animating JS based off Huntt theme.
                    masonryChild.each(
                        function( i ) {
                            // Show content.
                            setTimeout(
                                function() {
                                    masonryChild.eq( i ).addClass( 'post-loaded fade-in' );
                                }, 100 * ( i + 1 )
                            );
                        }
                    );

                    $( '#spinner' ).fadeOut(
                        250, function() {
                            $( this ).remove();
                        }
                    );
                }
            );
    }
);

} )( jQuery );

I know I've missed something but I'm not really sure. any help is appreciated :)

* Update *

I'm still having some issues with this... Needing to create a custom selective refresh Partial type makes total sense. So I added the javascript in the this thread: Add or remove HTML class with selective refresh? my customizer.js file which is being enqueued.

I Changed partialConstructor.body_class to partialConstructor.grid_class, updated the customizer.php file to also include the type like this:

$wp_customize->selective_refresh->add_partial(
    'dynamicgrid', array(
        'selector'          => '.posts-container',
        'type'              => 'grid_class',
        'settings'          => 'dynamicgrid',
        'render_callback'   => 'testtheme_customize_partial_grid_classes',
    )
);

and then back in my js file, I changed body = $( '.posts-container' ); so that this updates classes on the .posts-container div instead of the body tag as the example shows.

This seems to make sense to me but now I get an error in console:

Uncaught TypeError: Cannot read property 'partialConstructor' of undefined
at VM3068 customizer.js?ver=4.8.3:12
at VM3068 customizer.js?ver=4.8.3:91

Which means I've missed something or put it in the wrong place?

This is my entire customzier.js file if it helps?

/**
 * File customizer.js.
 *
 * Theme Customizer enhancements for a better user experience.
 * Contains handlers to make Theme Customizer preview reload changes asynchronously.
 *
 * @package Testtheme
 */

( function( $ ) {

wp.customize.selectiveRefresh.partialConstructor.grid_class = wp.customize.selectiveRefresh.Partial.extend({

    /**
     * Class name choices.
     *
     * This is populated in PHP via `wp_add_inline_script()`.
     *
     * @type {Array}
     */
    choices: [],

    /**
     * Refresh partial.
     *
     * Override refresh behavior to bypass partial refresh request in favor of direct DOM manipulation.
     *
     * @returns {jQuery.Promise} Resolved promise.
     */
    refresh: function() {
        var partial = this, setting, body, deferred, className;

        setting = wp.customize( partial.params.primarySetting );
        className = setting.get();
        body = $( '.posts-container' );
        body.removeClass( partial.choices.join( ' ' ) );
        body.addClass( className );

        // Do good diligence and return an expected value from the function.
        deferred = new $.Deferred();
        deferred.resolveWith( partial, _.map( partial.placements(), function() {
            return '';
        } ) );
        return deferred.promise();
    }
});

// Site title and description.
wp.customize(
    'blogname', function( value ) {
        value.bind(
            function( to ) {
                $( '.site-title span' ).text( to );
            }
        );
    }
);

wp.customize(
    'blogdescription', function( value ) {
        value.bind(
            function( to ) {
                $( '.site-description' ).text( to );
            }
        );
    }
);

// Grid Settings.
wp.customize(
    'dynamicgrid', function( value ) {
        value.bind(
            function( to ) {
                if ( 'standard-layout' === to ) {
                    $( '.posts-container' ).addClass( 'standard-layout' ).removeClass( 'two-grid-layout three-grid-layout four-grid-layout' );
                } else if ( 'two-grid-layout' === to ) {
                    $( '.posts-container' ).addClass( 'two-grid-layout' ).removeClass( 'standard-layout three-grid-layout four-grid-layout' );
                } else if ( 'three-grid-layout' === to ) {
                    $( '.posts-container' ).addClass( 'three-grid-layout' ).removeClass( 'standard-layout two-grid-layout four-grid-layout' );
                } else {
                    $( '.posts-container' ).addClass( 'four-grid-layout' ).removeClass( 'standard-layout two-grid-layout three-grid-layout' );
                }
            }
        );
    }
);




} )( jQuery );

* UPDATE NUMBER TWO *

This is my current javascript class with added masonry

wp.customize.selectiveRefresh.partialConstructor.grid_class = 
wp.customize.selectiveRefresh.Partial.extend({

    /**
     * Class name choices.
     *
     * This is populated in PHP via `wp_add_inline_script()`.
     *
     * @type {Array}
     */
    choices: [],

    /**
     * Refresh partial.
     *
     * Override refresh behavior to bypass partial refresh request in favor of direct DOM manipulation.
     *
     * @returns {jQuery.Promise} Resolved promise.
     */
    refresh: function() {
        var partial = this, setting, body, deferred, className;

        setting = wp.customize( partial.params.primarySetting );
        className = setting.get();
        body = $( '.posts-container' );
        if ( 'standard-layout' === className ) {
            body.removeClass( 'masonry-enabled' );
        } else {
            body.addClass( 'masonry-enabled' );
        }
        body.removeClass( partial.choices.join( ' ' ) );
        body.addClass( className );
        body.masonry( 'reloadItems' );
        body.masonry( 'layout' );

        // Do good diligence and return an expected value from the function.
        deferred = new $.Deferred();
        deferred.resolveWith( partial, _.map( partial.placements(), function() {
            return '';
        } ) );
        return deferred.promise();
    }


});
  • How is get_option( 'dynamicgrid' ) normally rendered out into the template on the frontend, outside the context of the customizer? Is it just adding classes to a .posts-container element? – Weston Ruter Nov 2 '17 at 0:58
  • If so, you may want to refer to my answer here: wordpress.stackexchange.com/a/273205/8521 – Weston Ruter Nov 2 '17 at 0:59
  • hey @WestonRuter, yes, its literally just adding a class to the .posts-container. I knew I must have been missing something, thanks :) – Kirsty Burgoine Nov 2 '17 at 7:12
  • hey @WestonRuter, I've updated my post above to include the js you suggested. I thought I'd done everything correctly but now I get an error in console which makes me think I must have put the .js in the wrong place or missed something simple? :( – Kirsty Burgoine Nov 3 '17 at 9:27
  • You have to enqueue the JS with a dependency on customize-selective-refresh. Remember to only enqueue this JS if in the Customizer preview. Inside a wp_enqueue_scripts callback you can check is_customize_preview(). – Weston Ruter Nov 3 '17 at 17:17

Your Answer

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

Browse other questions tagged or ask your own question.