Wordpress customizer custom control transport postMessage not working
Asked Answered
P

4

7

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.

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.

Persecute answered 11/1, 2016 at 14:6 Comment(0)
S
2

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' );
Swanhildas answered 1/5, 2021 at 17:26 Comment(0)
C
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

Carboy answered 2/5, 2021 at 18:11 Comment(0)
F
1

test3 will only fire when the value of custom_smthing changes.

Forayer answered 12/9, 2018 at 13:56 Comment(1)
I checked it myself. still doesnt fire even if the value changesAegis
A
0

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.

Aegis answered 3/5, 2021 at 12:27 Comment(4)
Well, did you check "Create an index.php file" in the WordPress theme handbook when creating your theme? And please don't expect every documentation to include something like "remember that your theme should call wp_head() and wp_footer() so that scripts and styles are loaded properly", and it is our job to find for the correct resources (documentation, tutorial, etc.). (Btw, I did not -1 your answer... But you should consider improving it.)Powel
@SallyCJ it's a fair expectation to make actually. I was making a minimalist example and didnt want to have headers and footers. How can i know they are responsible of loading styles and scripts. I thought they are just another superflous way from WP to make things more complicated and externalise index parts. Only now i learned the difference between wp_head() and get_header() and I think that it should have been covered and explained. If you pay close attention this wasn't my question. I just placed a bounty on it. Maybe you're just sad I didnt give it to you. That! Is what's not fair.Aegis
Rest assured, I was well-aware that you simply put a bounty on the question. And yes the (theme) handbook does not cover everything, so if something important is missing, feel free to contact or contribute to the docs team. And would you please edit your answer, maybe include the "I was making a minimalist example and didnt want to have headers and footers." part with your code and explain what happened and how did you fix the issue.Powel
And actually, if I were you, I would've asked if it's okay to remove the headers and footers, and the proper way to remove them. Also, I would be sad if a bounty was explicitly offered to me and yet it eventually awarded to someone else. Otherwise, I'd be just fine...Powel

© 2022 - 2024 — McMap. All rights reserved.