4

I need to add/remove controls dynamically in Customizer. Say I have a field No of pages and its value is 3. I want to render 3 dropdown pages controls. And when its value is changed, I want to add/remove controls accordingly.

Currently I am hacking it through PHP. Like looping the controls based on the numbers. Demerit of this approach is that, when number is changed, I have to save Customizer value and refresh the whole customizer page to reflect new controls.

I am looking for approach which would remove saving and refreshing of the page. I believe I need to dive into Customizer JS API. I would appreciate if someone would point me to right direction.

  • Is it important for you to also have the Preview pane reflect what you have in the customizer Iframe? – prosti Dec 22 '16 at 14:55
  • Do you create a theme or a plugin? – prosti Dec 22 '16 at 14:58
  • Hi, do you actually need to add existing controls to a single section? It is more like you just need HTML that should appear once you select an option inside the control. Your control can have as much as needed settings associated with it. So you could do that only in PHP and some JavaScript that will be on the side of the original control of yours – prosti Dec 22 '16 at 15:18
  • Yes, I want to reflect preview without having to save and refresh page again. I am using it in theme. – Nilambar Dec 23 '16 at 3:42
  • OK, but do you actually try to inject customizer controls live using JavaScript or you are OK with the solution to create one custom control that would have dynamic HTML injected? Would you provide some minimal image? – prosti Dec 23 '16 at 10:36
4

Ok so you can check out my repo with some custom controls

https://github.com/dingo-d/wordpress-theme-customizer-extra-custom-controls

I've adapted the contextual controls by Weston Ruters guide here:

https://make.xwp.co/2016/07/24/dependently-contextual-customizer-controls/

In my example in the repo I have the boxed body checkbox control that toggles boxed body.

You'll need to enqueue a script to put the js code in

add_action( 'customize_controls_enqueue_scripts', 'mytheme_customizer_control_toggle' );

/**
 * Custom contextual controls
 *
 * @since 1.0.0
 */
function mytheme_customizer_control_toggle() {
    wp_enqueue_script( 'mytheme-contextualcontrols', get_template_directory_uri() . '/inc/customizer/js/customizer-contextual.js?v=' . rand(), array( 'customize-controls' ), false );
}

And in your customizer-contextual.js you'll have something like:

( function( api ) {
    'use strict';

    api.bind( 'ready', function() {

        api( 'boxed_body', function(setting) {
            var linkSettingValueToControlActiveState;

            /**
             * Update a control's active state according to the boxed_body setting's value.
             *
             * @param {api.Control} control Boxed body control.
             */
            linkSettingValueToControlActiveState = function( control ) {
                var visibility = function() {
                    if ( true === setting.get() || 1 === setting.get() ) {
                        control.container.slideDown( 180 );
                    } else {
                        control.container.slideUp( 180 );
                    }
                };

                // Set initial active state.
                visibility();
                // Update activate state whenever the setting is changed.
                setting.bind( visibility );
            };

            // Call linkSettingValueToControlActiveState on the border controls when they exist.
            api.control( 'boxed_body_border_width', linkSettingValueToControlActiveState );
            api.control( 'boxed_body_border_color', linkSettingValueToControlActiveState );
            api.control( 'boxed_body_border_style', linkSettingValueToControlActiveState );
        });

    });

}( wp.customize ) );

You are targeting the control name (in this case it's 'boxed body'), inside it you can check if that controle has active state or not, and accordingly set the 'visibility' of the other linked controls.

You can also toggle this change in the preview screeen by hooking to customize_preview_init hook

add_action( 'customize_preview_init', 'mytheme_customizer_live_preview' );
/**
 * Live preview script enqueue
 *
 * @since 1.0.0
 */
function mytheme_customizer_live_preview() {
    wp_enqueue_script( 'mytheme-themecustomizer', get_template_directory_uri() . '/inc/customizer/js/customizer.js?v=' . rand(), array( 'jquery', 'customize-preview' ), false );
}

Inside customizer.js you'll have something like:

(function($, api) {
    'use strict';

    // Boxed Body Toggle.
    api( 'boxed_body', function(value) {
        value.bind(function(newval) {
            if (newval) {
                $( 'body' ).wrapInner( '<div class="boxed_body_wrapper" />' );
            } else {
                $( '.boxed_body_wrapper' ).contents().unwrap();
            }
        });
    });

})(jQuery, wp.customize);

Hope this helps :)

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.