WordPress customizer custom control transport postMessage not working

I’m building a WordPress theme and need to add custom controls in the customizer, the input field is showing up but when I change the value of input nothing happens.

Here is my code.

Read More
class WP_Customize_Custom_Control extends WP_Customize_Control {
  public $type = 'custom_control';

  function render_content(){
  }
  public function content_template() {
    ?>
    <input type="text" id="custom_control" name="custom_control" />
    <?php
  }
}

function company_customize_register( $wp_customize ){
  $wp_customize->register_control_type( 'WP_Customize_Custom_Control' );
  $wp_customize->add_setting('custom_smthing', array( 'default' => get_theme_mod( "custom_smthing" ), 'transport' =>'postMessage' ) );
  $wp_customize->add_control(new WP_Customize_Custom_Control($wp_customize,'custom_smthing',
    array(
      'label'      => __( 'Custom Control', 'company' ),
      'section'    => 'body_backgrounds',
      'settings'   => 'custom_smthing',
     )
   )
  );
}
add_action( 'customize_register', 'company_customize_register' );

and the js is

( function( $ ) {
  console.log("test1");
  wp.customize( 'custom_smthing', function( value ) {
    console.log("test2");
    value.bind( function( to ) {
      console.log("test3");
    } );
  });
})( jQuery );

test1 and test2 are working but test3 never fires.

Related posts

4 comments

  1. Maybe my answer is not what are you looking for, but content_template is for underscore JS templates. I’m not completely sure by your answer do you need it or not. But you can find additional information here.

    If you remove register_control_type line and relocate your input into render_content method it will do a trick.

    Your PHP part will be like

    class WP_Customize_Custom_Control extends WP_Customize_Control {
      public $type = 'custom_control';
    
      public function render_content() {
        ?>
        <label>
            <span class="customize-control-title"><?php echo esc_html( $this->label ); ?></span>
                <input class="custom_control" id="custom_control" type="text" <?php $this->link(); ?> value="<?php echo esc_attr( $this->value() ); ?>">
            </label>
        <?php
      }
    }
    
    function company_customize_register( $wp_customize ){
    
      // $wp_customize->register_control_type( 'WP_Customize_Custom_Control' ); - remove this line
    
      $wp_customize->add_setting('custom_smthing', array( 'default' => get_theme_mod( "custom_smthing" ), 'transport' =>'postMessage' ) );
    
      $wp_customize->add_control(new WP_Customize_Custom_Control($wp_customize,'custom_smthing',
        array(
          'label'      => __( 'Custom Control', 'company' ),
          'section'    => 'body_backgrounds',
          'settings'   => 'custom_smthing',
         )
       )
      );
    }
    add_action( 'customize_register', 'company_customize_register' );
    
  2. I Revised your code and found out that your code will not work in many scenarios or as per the latest WP version.

    You did not mention the body_backgrounds section in your code. so I assume that Body Backgrounds is your custom section because I did not find the default body_backgrounds section in WordPress.

    So I added a section.

    $wp_customize->add_section( 'body_backgrounds' , array(
        'title'      => 'Body Backgrounds',
        'priority'   => 20,
    ) );
    

    WP_Customize_Control is only loading when the theme customizer is actually used. So, you need to define your class within the function ‘company_customize_register’. Otherwise, it will give PHP Fatal error: Class 'WP_Customize_Control' not found

    You did not mention how you enqueue your js but better add dependency jquery and customize-preview.

    function customizer_live_preview() {
        wp_enqueue_script(
            'theme-customizer',
            get_template_directory_uri() . '/assets/js/theme-customizer.js',
            array( 'jquery', 'customize-preview' ),
            '1.0.0',
            true
        );
    }
    add_action( 'customize_preview_init', 'customizer_live_preview' );
    

    You need to pass the data-customize-setting-link to your input to bind your value.

    <input type="text" id="custom_smthing" name="custom_smthing" data-customize-setting-link="custom_smthing" />
    

    PHP

    function company_customize_register( $wp_customize ){
    
        class WP_Customize_Custom_Control extends WP_Customize_Control {
            public $type = 'custom_control';
    
            function render_content(){ }
            
            public function content_template() {?>
                <input type="text" id="custom_smthing" name="custom_smthing" data-customize-setting-link="custom_smthing" />
            <?php }
        }
    
        $wp_customize->register_control_type( 'WP_Customize_Custom_Control' );
        $wp_customize->add_section( 'body_backgrounds' , array(
            'title'      => 'Body Backgrounds',
            'priority'   => 20,
        ) );
        $wp_customize->add_setting('custom_smthing', array( 'default' => get_theme_mod( "custom_smthing" ) ? get_theme_mod( "custom_smthing" ) : '', 'transport' =>'postMessage' ) );
        $wp_customize->add_control(new WP_Customize_Custom_Control($wp_customize,'custom_smthing',
                array(
                    'label'      => __( 'Custom Control', 'company' ),
                    'section'    => 'body_backgrounds',
                    'settings'   => 'custom_smthing',
                )
            )
        );
    }
    add_action( 'customize_register', 'company_customize_register' );
    
    function customizer_live_preview() {
        wp_enqueue_script(
            'theme-customizer',
            get_template_directory_uri() . '/assets/js/theme-customizer.js',
            array( 'jquery', 'customize-preview' ),
            '1.0.0',
            true
        );
    }
    add_action( 'customize_preview_init', 'customizer_live_preview' );
    

    “theme-customizer.js”

    (function( $ ) {
        "use strict";
    
        wp.customize('custom_smthing', function(value) {
            value.bind(function(value) {
                console.log(value);
            });
        });
    
    })( jQuery );
    

    Tested and works.

    enter image description here

  3. I have figured out the issue.
    if the first two logs are fired then nothing is wrong in the question
    there are no mistakes there and all is as instructed in the official wordpress themes development handbook.
    the issue was in index.php
    wp_head(); and wp_footer(); MUST exist
    I removed them = only first two logs are fired
    I put them on = all three logs are fired
    what makes me angry is WHY this wasn’t mentioned in the wordpress official handbook.
    at the very end of the entire handbook yes
    but it doesn’t say it is essential for many things to work, including this one.

Comments are closed.