Support » Alpha/Beta/RC » Issue with wp_localize_script() or similar on block themes?

  • Resolved Sanjeev Aryal

    (@sanzeeb3)


    I’m using a development version (5.9-beta4-52409).

    It looks like the wp_localize_script() isn’t working as expected on any block theme such as Twenty Twenty-Two.

    Here’s the code snippet in the theme’s functions.php

    add_action( 'wp_enqueue_scripts', function() {
    	wp_register_script( 'my-script', 'https://example.com/script.js', array(), '0.0.1', false );
    } );
    
    add_shortcode( 'my_shortcode', function() {
    	wp_enqueue_script( 'my-script' );
    
    	wp_localize_script( 
    		'my-script',
    		'my_params',
    		array( 
    			'is_okay' => 'Yes'
    		)
    	);
    
    	return 'Shortcode Content';
    
    } );

    Upon adding the shortcode and visiting the page. The script.js is enqueued, but the localization isn’t working. There’s an error “my_params” is not defined in the console.

    The page I need help with: [log in to see the link]

Viewing 4 replies - 1 through 4 (of 4 total)
  • Moderator bcworkz

    (@bcworkz)

    You cannot use wp_localize_script() from within a shortcode callback. It executes at the wrong time in there. It needs to be called in the same context as the enqueued script that it’s related to. If the data you need to pass is only available to the shortcode callback, instead of wp_localize_script(), you could simply add the JS declarations within <script> tags and include them with any other returned shortcode content.

    FWIW, wp_localize_script() was not intended for use in passing random data from PHP to page scripts. It really is meant for localization and internationalization. But it served the alternative use as well, so now we see it in examples everywhere. But now there’s a more appropriate function: wp_add_inline_script(). It basically works the same way, it’s just that the function name is more appropriate for the intended use.

    Thread Starter Sanjeev Aryal

    (@sanzeeb3)

    Thank you for sharing the details.

    this can still be achieved with an anonymous call hooked on the wp_footer action,

    
    $data=array();// your data object you want to pass to your front-end script.
    $localise = json_encode($data);
    add_action('wp_footer', function() use ($localise){
      printf('<script type="text/javascript">var myData = %s</script>', $localise);
    });
    

    I myself have just stumbled upon this issue.

    As @sanzeeb3 pointed out, this works perfectly fine in traditional themes but stops working only in block themes. It turns out that wp_enqueue_scripts fires later in block themes than it does in traditional ones. As a consequence, when you try to enqueue a script simply using its handle, the script is not found in the list of the registered scripts. And, in turn, wp_localize_script/wp_add_inline_script fail to find the handle to attach their data to.

    Still, this is perfectly achievable by using wp_localize_script/wp_add_inline_script. The following code amends what @sanzeeb3 originally had and works in block themes as well as traditional ones, without resorting to a wp_footer callback:

    
    add_action( 'wp_enqueue_scripts', function() {
    	wp_register_script( 'my-script', 'https://example.com/script.js', array(), '0.0.1', false );
    } );
    
    add_shortcode( 'my_shortcode', function() {
    	if ( ! wp_script_is( 'my-script', 'registered' ) ) {
    		wp_register_script( 'my-script', 'https://example.com/script.js', array(), '0.0.1', false );
    	}
    
    	wp_enqueue_script( 'my-script' );
    
    	wp_localize_script( 
    		'my-script',
    		'my_params',
    		array( 
    			'is_okay' => 'Yes'
    		)
    	);
    
    	return 'Shortcode Content';
    
    } );
    

    Please note that it is enough to verify whether the script has already been registered. In case it hasn’t (because in block themes wp_enqueue_scripts has not fired yet), the script can be registered at this time, inside the shortcode. A similar condition could be added to the wp_enqueue_scripts callback but that would be redundant because wp_register_script() invokes wp_scripts()->add() which immediately bails out if the script has already been registered.

    With that adjustment alone, the original code from @sanzeeb3 works just fine.

    I hope this can help others.

    PS: if you consider that is conceptually impossible for WordPress to register a script twice, the condition can even be removed and the script will be registered inside the shortcode: if it is already registered, wp_register_script() will return prematurely anyway, so it is just a matter of preference and code style.

Viewing 4 replies - 1 through 4 (of 4 total)
  • You must be logged in to reply to this topic.