theme customizer - Customiser `active_callback` not working on control with `postMessage` transport method

admin2025-06-02  0

I have 4x custom settings within 2x custom sections, with the second setting in each section relying on an active_callback to show/hide it.

In both cases the active_callback checks the value of the first custom setting from that section, and it was working perfectly until I started using transport => postMessage for the first setting (all settings below, as it's easier to show them than it is explain them).

There are no JS errors, so I assume it must be something to do with how the active callback is fired (I.e. perhaps it's not when postMessage is used).

While I can add some additional JS to cover my requirements, I'd be curious to know whether or not this is expected behavior, and if it is, whether or not there is a way to fix my problem.

Here are the settings (registered using the customize_register action hook)...

/**
 * Create the custom 'Archive Pages' section and register settings
 */
function register_settings_archive_template($wp_customise){

    $wp_customise->add_section('section_template_archive' , array(
        'title'             => __('Archive Pages', TEXT_DOMAIN),
        'priority'          => 60
    ));

    /**
     * Link tile size (overrides General setting)
     */

    $wp_customise->add_setting('archive_link_tile_size', array(
        'default'   => 'default',
        'transport' => 'postMessage'
    ));

    $wp_customise->add_control('archive_link_tile_size', array(
        'label'         => __('Link tile size', TEXT_DOMAIN),
        'section'       => 'section_template_archive',
        'type'          => 'radio',
        'choices'       => array(
            'default'   => __('Default', TEXT_DOMAIN),
            'large'     => __('Large', TEXT_DOMAIN),
            'small'     => __('Small', TEXT_DOMAIN)
        ),
        'description'   => __('The size of link tile that you wish to dsipay on archive pages.', TEXT_DOMAIN),
    ));

    /**
     * Show 'More...' link
     */

    $wp_customise->add_setting('archive_show_more_link', array(
        'default'   => false,
        'transport' => 'postMessage'
    ));

    $wp_customise->add_control('archive_show_more_link', array(
        'label'             => __('Show link to Link/Post', TEXT_DOMAIN),
        'section'           => 'section_template_archive',
        'type'              => 'checkbox',
        'description'       => __('Whether or not to show the \'More...\' link underneath a large link tile on archive pages.  Note that links cannot be displayed in conjunction with \'Small\' Link Tiles.', TEXT_DOMAIN),
        'active_callback'   => '_check_is_link_tile_size_large'
    ));

}

/**
 * Create the custom 'Search Results' section and register settings
 */
function register_settings_search_template($wp_customise){

    $wp_customise->add_section('section_template_search' , array(
        'title'             => __('Search Results', TEXT_DOMAIN),
        'priority'          => 60
    ));

    /**
     * Link tile size (overrides General setting)
     */

    $wp_customise->add_setting('search_link_tile_size', array(
        'default'   => 'default',
        'transport' => 'postMessage'
    ));

    $wp_customise->add_control('search_link_tile_size', array(
        'label'         => __('Link tile size', TEXT_DOMAIN),
        'section'       => 'section_template_search',
        'type'          => 'radio',
        'choices'       => array(
            'default'   => __('Default', TEXT_DOMAIN),
            'large'     => __('Large', TEXT_DOMAIN),
            'small'     => __('Small', TEXT_DOMAIN)
        ),
        'description'   => __('The size of link tile that you wish to dsipay on the search results page.', TEXT_DOMAIN)
    ));

    /**
     * Show 'More...' link
     */

    $wp_customise->add_setting('search_show_more_link', array(
        'default'   => false,
        'transport' => 'postMessage'
    ));

    $wp_customise->add_control('search_show_more_link', array(
        'label'             => __('Show link to Link/Post', TEXT_DOMAIN),
        'section'           => 'section_template_search',
        'type'              => 'checkbox',
        'description'       => __('Whether or not to show the \'More...\' link underneath a large link tile on the search results page.  Note that links cannot be displayed in conjunction with \'Small\' Link Tiles.', TEXT_DOMAIN),
        'active_callback'   => '_check_is_link_tile_size_large'
    ));

}

And here is the active callback...

public function _check_is_link_tile_size_large($control){

    $control_id = $control->id;

    switch($control_id):

        case 'archive_show_more_link' :
            $validation_setting = 'archive_link_tile_size';
            break;

        case 'search_show_more_link' :
            $validation_setting = 'search_link_tile_size';
            break;

    endswitch;

    return ($control->manager->get_setting($validation_setting)->value() === 'large');

}

Update

I should have added this in the first place, but here is the JS that I am using to update the above settings via postMessage -

(function($){

    var api = wp.customize;

    CustomiseArchivePages();    // Customise settings in the Archive Pages section
    CustomiseSearchResults();   // Customise settings in the Search Results section

    /**
     * Customise settings in the Archive Pages section
     */
    function CustomiseArchivePages(){

        /** Link Tile size */
        api('archive_link_tile_size', function(value){
            value.bind(function(newval){
                PreviewLinkTile(newval, api.get().archive_show_more_link);
            });
        });

        /** Show/hide 'More...' button  */
        api('archive_show_more_link', function(value){
            value.bind(function(newval){
                PreviewLinkTile(api.get().archive_link_tile_size, newval);
            }); 
        });

    }

    /**
     * Customise settings in the Search Results section
     */
    function CustomiseSearchResults(){

        /** Search box placeholder text */
        api('search_box_placeholder', function(value){
            value.bind(function(newval){
                $('input.s').attr('placeholder', newval);
            });
        });

        /** Link Tile size */
        api('search_link_tile_size', function(value){
            value.bind(function(newval){
                PreviewLinkTile(newval, api.get().search_show_more_link);
            });
        });

        /** Show/hide 'More...' button  */
        api('search_show_more_link', function(value){
            value.bind(function(newval){
                PreviewLinkTile(api.get().search_link_tile_size, newval);
            });
        });

    }

    /**
     * Set the link tile size and show/hide the 'More...' button on link tiles
     *
     * @param required string linkTileSize          The size of the link tiles that are being displayed
     * @param required string showMoreInfoButton    Whether or not to show the 'More...' button
     */
    function PreviewLinkTile(linkTileSize, showMoreInfoButton){

        var linksContainer = $('#links-container'),         // The links container
            linkTiles = $('.link-tile', linksContainer);    // Every individual link tile

        linkTileSize = (linkTileSize !== 'default') ? linkTileSize : api.get().general_link_tile_size;  // If the new size is default, grab the default size

        /**
         * Set the link tile size
         */
        switch(linkTileSize){

            case 'large' :

                /** Set the links container classes */
                linksContainer.removeClass('uk-grid-width-1-2 uk-grid-width-small-1-3 uk-grid-width-medium-1-4 uk-grid-width-large-1-5')
                    .addClass('uk-grid-width-1-1 uk-grid-width-small-1-1 uk-grid-width-medium-1-2 uk-grid-width-large-1-3');

                /** Set the link tile class */
                linkTiles.removeClass('link-tile-small')
                    .addClass('link-tile-large');

                break;

            case 'small' :

                /** Set the links container classes */
                linksContainer.removeClass('uk-grid-width-1-1 uk-grid-width-small-1-1 uk-grid-width-medium-1-2 uk-grid-width-large-1-3')
                    .addClass('uk-grid-width-1-2 uk-grid-width-small-1-3 uk-grid-width-medium-1-4 uk-grid-width-large-1-5');

                /** Set the link tile class */
                linkTiles.removeClass('link-tile-large')
                    .addClass('link-tile-small');

                break;

            default :
                console.log('An unexpected error occured when customising the Link Tile size: The new size could not be determined.');
                break;

        }

        /**
         * Show/hide the 'More...' button
         */
        if(showMoreInfoButton && linkTileSize === 'large'){
            linkTiles.addClass('show-more-button');
        } else {
            linkTiles.removeClass('show-more-button');
        }

    }

})(jQuery);

I have 4x custom settings within 2x custom sections, with the second setting in each section relying on an active_callback to show/hide it.

In both cases the active_callback checks the value of the first custom setting from that section, and it was working perfectly until I started using transport => postMessage for the first setting (all settings below, as it's easier to show them than it is explain them).

There are no JS errors, so I assume it must be something to do with how the active callback is fired (I.e. perhaps it's not when postMessage is used).

While I can add some additional JS to cover my requirements, I'd be curious to know whether or not this is expected behavior, and if it is, whether or not there is a way to fix my problem.

Here are the settings (registered using the customize_register action hook)...

/**
 * Create the custom 'Archive Pages' section and register settings
 */
function register_settings_archive_template($wp_customise){

    $wp_customise->add_section('section_template_archive' , array(
        'title'             => __('Archive Pages', TEXT_DOMAIN),
        'priority'          => 60
    ));

    /**
     * Link tile size (overrides General setting)
     */

    $wp_customise->add_setting('archive_link_tile_size', array(
        'default'   => 'default',
        'transport' => 'postMessage'
    ));

    $wp_customise->add_control('archive_link_tile_size', array(
        'label'         => __('Link tile size', TEXT_DOMAIN),
        'section'       => 'section_template_archive',
        'type'          => 'radio',
        'choices'       => array(
            'default'   => __('Default', TEXT_DOMAIN),
            'large'     => __('Large', TEXT_DOMAIN),
            'small'     => __('Small', TEXT_DOMAIN)
        ),
        'description'   => __('The size of link tile that you wish to dsipay on archive pages.', TEXT_DOMAIN),
    ));

    /**
     * Show 'More...' link
     */

    $wp_customise->add_setting('archive_show_more_link', array(
        'default'   => false,
        'transport' => 'postMessage'
    ));

    $wp_customise->add_control('archive_show_more_link', array(
        'label'             => __('Show link to Link/Post', TEXT_DOMAIN),
        'section'           => 'section_template_archive',
        'type'              => 'checkbox',
        'description'       => __('Whether or not to show the \'More...\' link underneath a large link tile on archive pages.  Note that links cannot be displayed in conjunction with \'Small\' Link Tiles.', TEXT_DOMAIN),
        'active_callback'   => '_check_is_link_tile_size_large'
    ));

}

/**
 * Create the custom 'Search Results' section and register settings
 */
function register_settings_search_template($wp_customise){

    $wp_customise->add_section('section_template_search' , array(
        'title'             => __('Search Results', TEXT_DOMAIN),
        'priority'          => 60
    ));

    /**
     * Link tile size (overrides General setting)
     */

    $wp_customise->add_setting('search_link_tile_size', array(
        'default'   => 'default',
        'transport' => 'postMessage'
    ));

    $wp_customise->add_control('search_link_tile_size', array(
        'label'         => __('Link tile size', TEXT_DOMAIN),
        'section'       => 'section_template_search',
        'type'          => 'radio',
        'choices'       => array(
            'default'   => __('Default', TEXT_DOMAIN),
            'large'     => __('Large', TEXT_DOMAIN),
            'small'     => __('Small', TEXT_DOMAIN)
        ),
        'description'   => __('The size of link tile that you wish to dsipay on the search results page.', TEXT_DOMAIN)
    ));

    /**
     * Show 'More...' link
     */

    $wp_customise->add_setting('search_show_more_link', array(
        'default'   => false,
        'transport' => 'postMessage'
    ));

    $wp_customise->add_control('search_show_more_link', array(
        'label'             => __('Show link to Link/Post', TEXT_DOMAIN),
        'section'           => 'section_template_search',
        'type'              => 'checkbox',
        'description'       => __('Whether or not to show the \'More...\' link underneath a large link tile on the search results page.  Note that links cannot be displayed in conjunction with \'Small\' Link Tiles.', TEXT_DOMAIN),
        'active_callback'   => '_check_is_link_tile_size_large'
    ));

}

And here is the active callback...

public function _check_is_link_tile_size_large($control){

    $control_id = $control->id;

    switch($control_id):

        case 'archive_show_more_link' :
            $validation_setting = 'archive_link_tile_size';
            break;

        case 'search_show_more_link' :
            $validation_setting = 'search_link_tile_size';
            break;

    endswitch;

    return ($control->manager->get_setting($validation_setting)->value() === 'large');

}

Update

I should have added this in the first place, but here is the JS that I am using to update the above settings via postMessage -

(function($){

    var api = wp.customize;

    CustomiseArchivePages();    // Customise settings in the Archive Pages section
    CustomiseSearchResults();   // Customise settings in the Search Results section

    /**
     * Customise settings in the Archive Pages section
     */
    function CustomiseArchivePages(){

        /** Link Tile size */
        api('archive_link_tile_size', function(value){
            value.bind(function(newval){
                PreviewLinkTile(newval, api.get().archive_show_more_link);
            });
        });

        /** Show/hide 'More...' button  */
        api('archive_show_more_link', function(value){
            value.bind(function(newval){
                PreviewLinkTile(api.get().archive_link_tile_size, newval);
            }); 
        });

    }

    /**
     * Customise settings in the Search Results section
     */
    function CustomiseSearchResults(){

        /** Search box placeholder text */
        api('search_box_placeholder', function(value){
            value.bind(function(newval){
                $('input.s').attr('placeholder', newval);
            });
        });

        /** Link Tile size */
        api('search_link_tile_size', function(value){
            value.bind(function(newval){
                PreviewLinkTile(newval, api.get().search_show_more_link);
            });
        });

        /** Show/hide 'More...' button  */
        api('search_show_more_link', function(value){
            value.bind(function(newval){
                PreviewLinkTile(api.get().search_link_tile_size, newval);
            });
        });

    }

    /**
     * Set the link tile size and show/hide the 'More...' button on link tiles
     *
     * @param required string linkTileSize          The size of the link tiles that are being displayed
     * @param required string showMoreInfoButton    Whether or not to show the 'More...' button
     */
    function PreviewLinkTile(linkTileSize, showMoreInfoButton){

        var linksContainer = $('#links-container'),         // The links container
            linkTiles = $('.link-tile', linksContainer);    // Every individual link tile

        linkTileSize = (linkTileSize !== 'default') ? linkTileSize : api.get().general_link_tile_size;  // If the new size is default, grab the default size

        /**
         * Set the link tile size
         */
        switch(linkTileSize){

            case 'large' :

                /** Set the links container classes */
                linksContainer.removeClass('uk-grid-width-1-2 uk-grid-width-small-1-3 uk-grid-width-medium-1-4 uk-grid-width-large-1-5')
                    .addClass('uk-grid-width-1-1 uk-grid-width-small-1-1 uk-grid-width-medium-1-2 uk-grid-width-large-1-3');

                /** Set the link tile class */
                linkTiles.removeClass('link-tile-small')
                    .addClass('link-tile-large');

                break;

            case 'small' :

                /** Set the links container classes */
                linksContainer.removeClass('uk-grid-width-1-1 uk-grid-width-small-1-1 uk-grid-width-medium-1-2 uk-grid-width-large-1-3')
                    .addClass('uk-grid-width-1-2 uk-grid-width-small-1-3 uk-grid-width-medium-1-4 uk-grid-width-large-1-5');

                /** Set the link tile class */
                linkTiles.removeClass('link-tile-large')
                    .addClass('link-tile-small');

                break;

            default :
                console.log('An unexpected error occured when customising the Link Tile size: The new size could not be determined.');
                break;

        }

        /**
         * Show/hide the 'More...' button
         */
        if(showMoreInfoButton && linkTileSize === 'large'){
            linkTiles.addClass('show-more-button');
        } else {
            linkTiles.removeClass('show-more-button');
        }

    }

})(jQuery);
Share Improve this question edited Dec 16, 2015 at 16:26 David Gard asked Dec 14, 2015 at 16:14 David GardDavid Gard 3,3105 gold badges26 silver badges39 bronze badges 3
  • Yes, it is expected that if using postMessage, the active_callback wouldn't fire because it is only called when the preview refreshes. If you want to re-evaluate the active_callback handlers, you can refresh the preview via wp.customize.previewer.refresh() – Weston Ruter Commented Dec 15, 2015 at 5:48
  • 1 Thanks, but if I refresh then it totally destroys the point of using postMessage in the first place. Plus wp.customize.previewer.refresh() generates an error... – David Gard Commented Dec 15, 2015 at 11:02
  • Yes, good point. See my answer below. – Weston Ruter Commented Dec 16, 2015 at 6:11
Add a comment  | 

1 Answer 1

Reset to default 5

Because postMessage uses JavaScript entirely, any PHP active_callback will not get called unless the preview refreshes (e.g. via wp.customize.previewer.refresh()). So what you need to do is implement the active callback in JavaScript instead, like so:

wp.customize.bind( 'ready', function () {
    wp.customize.control( 'archive_show_more_link', function( control ) {
        var setting = wp.customize( 'archive_link_tile_size' );
        control.active.set( 'large' === setting.get() );
        setting.bind( function( value ) {
            control.active.set( 'large' === value );
        } );
    } );

    wp.customize.control( 'search_show_more_link', function( control ) {
        var setting = wp.customize( 'search_link_tile_size' );
        control.active.set( 'large' === setting.get() );
        setting.bind( function( value ) {
            control.active.set( 'large' === value );
        } );
    } );
} );

Make sure that this script gets enqueued into the Customizer pane and not the Customizer preview. In other words, enqueue the JS at the customize_controls_enqueue_scripts action.

转载请注明原文地址:http://conceptsofalgorithm.com/Algorithm/1748844978a314200.html

最新回复(0)