Returning ACF field data from Controller for use with Javascript

I am trying to make some ACF fields data available to Javascript.

I have my localize_script() set up in my add_action() filter in Setup.php:

add_action('wp_enqueue_scripts', function () {
    wp_enqueue_style('sage/main.css', asset_path('styles/main.css'), false, null);
    wp_enqueue_script('sage/main.js', asset_path('scripts/main.js'), ['jquery'], null, true);

    if (is_single() && comments_open() && get_option('thread_comments')) {
        wp_enqueue_script('comment-reply');
    }

    wp_localize_script('sage/main.js', 'testimonialQuote', \App\Controllers\Testimonials::testimonialQuote());
    
}, 100);


I want to this field to be accessible to my testimonials.blade.php view. Note: this this view is in a blocks folder if that matters.

Here is my controller:

<?php
namespace App\Controllers;

use Sober\Controller\Controller;

class Testimonials extends Controller {

    public static function testimonialQuote() {
     
        return get_field('testimonial_quote');
    }
}

I’ve tested this out by replacing “get_field(‘testimonial_quote’)” with a string and the javascript in my common.js is able to retrieve it.

To further debug, I tried accessing this in my testimonials.blade.php file like so:

@php
$testimonial_quote = Testimonials::testimonialQuote();
@endphp
<div class="testimonials-wrapper">
  @if($testimonial_quote)
    <p>{!!$testimonial_quote!!}</p>
    @else <p>nope!</p>
  @endif
</div>

It also returns null here. But when I attempt to render it directly in the above blade file using the get_field method, it works.

Therefore, there is something wrong with my controller, but the answers that have worked for others in this Discourse have not resolved the issue for me. Any idea what I am missing?

When you call get_field() without passing a second parameter, it attempts to “guess” one from the context it’s called in (i.e. it looks for the $post global to determine the post ID). If it can’t determine a context or determines the wrong one (i.e. not the one where your data actually is) then it will return null. My guess that because of how you’re accessing it here, it’s running into this issue. It also may have to do with how Controller loads static methods in certain contexts. This:

I’ve tested this out by replacing “get_field(‘testimonial_quote’)” with a string and the javascript in my common.js is able to retrieve it.

Strongly suggests, to me, that the issue is with the context in which you call get_field() not necessarily the Controller specifically.

IMO static methods on Controllers are not a great way to organization functionality and can lead to problems like the one you’re seeing here. If you need to get this value in two “places” (i.e. in your view and when enqueuing your JS) then I could recommend extracting the logic to retrieve the data to another location and to a function that takes an argument telling it where to find the value (i.e. a post ID) and then calling that logic in the Controller and when enqueuing.

So I feel dumb. I realized I didn’t save my testimonial_quote field in the block on the admin side before testing it out. That is why get_field was returning null in my testimonial controller.

However, my Javascript is still not picking up the field. Could this still be a context problem?

Does your field return an array? wp_localize_script requires an array for the third parameter:

(array) (Required) The data itself. The data can be either a single or multi-dimensional array.

It wasn’t. I changed the third parameter to an array like so:

  wp_localize_script('sage/main.js', 'testimonialQuote', 
    array('quote' => \App\Controllers\Testimonials::testimonialQuote()));

When I console testimonialQuote, it returns:

Object { quote: null }

I know it’s not a lifecycle issue either. I tested this out by trying to retrieve the textContent of the testimonial-wrapper paragraph and it retrieved it just fine.

I know there are ways around this issue, but I wanted to keep my blades as clean as possible. I’ve also looked into using the ACF Javascript API, but I haven’t had any lucking getting it up and running.

1 Like

This topic was automatically closed after 42 days. New replies are no longer allowed.