ACF Post Object: Get post data

I’m having trouble understanding how to get data from posts, configured in an ACF Post Object field. It’s possible to configure the Post Object field to return it’s value as post IDs or Post Objects. But the Post Object doesn’t contain all needed information, like the featured image.

I want to build a slider for my front-page, the slides should contain the link to the configured post and show the title and featured image. The title is passed with ACF, the link I’m able to generate using post_name, but the featured-image isn’t available.

So I need to fetch the whole post, I guess. But I can’t figure out how to retrieve more data, when I’m working in a component.

This is the wp-json endpoint:
https://frontity.noesteprojecten.nl/wp-json/acf/v3/options/options

This is my slider component

import React from "react";
import { connect, styled } from "frontity";
import SwipeableViews from 'react-swipeable-views';
import { autoPlay, bindKeyboard } from 'react-swipeable-views-utils';

const AutoPlaySwipeableViews = bindKeyboard(autoPlay(SwipeableViews));

const styles = {
   ...
};

const Slider = ({ state, actions }) => {
   const options = state.source.get("acf/options");
   const sliderItems = options.acf.home_slider_items;

   let slides = [];
   for (let i = 0; i < sliderItems.length; i++) {
      const postLinkPrefix = (sliderItems[i].post_type != 'post') ? '/' + sliderItems[i].post_type : '';

      slides.push(<Slide href={postLinkPrefix + "/" + sliderItems[i].post_name} style={Object.assign({}, styles.slide, styles['slide' + i % 3])}>slide n°{i}: {sliderItems[i].post_title}</Slide>);
   }

   return (
      <AutoPlaySwipeableViews enableMouseEvents>
         {slides}
      </AutoPlaySwipeableViews>
   );
}

export default connect(Slider);

Here’s a link to my repository: https://bitbucket.org/noesteijver/frontity/src/master/

Anyone? :smiley:

Is any information missing?

Hi @dominique

There’s a couple of approaches we could take here. The first is to try adding featured images to the REST API. I found this code snippet that you could add to functions.php or in a custom plugin: https://fancysquares.blog/wordpress-rest-api-add-featured-image-to-acf-relationship-post-object

The other way would be to get the ID of the post that you want and fetch it separately. Let me know how you get on with the first solution and if that fails then we can look at doing this.

Hi @mburridge, for this specific case I guess it would be sufficient to just add the featured-image to the output of ACF. Thanks for the link. I think I can solve this problem that way.

But still, I am wondering how to retrieve information of a specific post/term in a component. Because there are so much more fragments of data which you’d want to use, than that ACF is handing over by default. I don’t think it should be that way that you’d need to manually add this data to ACF, while the data is available if you’d be able to retrieve the whole post.

Think about data like:

  • featured image
  • excerpt (ACF only outputs it if you’ve manually set it)
  • rendered content (ACF only outputs unrendered post-content)
  • post template
  • attached ACF fields

I am bumping my way through this, and got a bit further now.

I’ve added this filter to my WordPress installation:

function get_featured_image_of_post_object( $item, $request ) {
	if ( isset( $item['acf']['home_slider_items'] ) ) {
		foreach ( $item['acf']['home_slider_items'] as $key => $post_object ) {

      $post_object_id = $post_object->ID;
      $featured = wp_get_attachment_image_src( get_post_thumbnail_id( $post_object_id ), 'full' );
      $featured_image_id = get_post_thumbnail_id($post_object_id);

			if ( $featured_image_id ) {
				$item['acf']['home_slider_items'][ $key ]->featured_media = $featured_image_id;
			}
		}
	}

	return $item;
}
add_filter('acf/rest_api/option/get_fields', 'get_featured_image_of_post_object', 10, 2);

This results in having the ID of the featured-image in the REST output. And I can use this in my slider.js file. However, the featured-image is not being rendered on the front-page. When I visit ‘Blogs’ and return to the front-page, it is being rendered. So it looks like it isn’t fetched when visiting the front-page.

To replicate:

  1. Visit: https://frontity-test-98427dzn9.vercel.app/
  2. Then click ‘Blogs’ in the nav bar;
  3. Return to ‘Home’, now the slider contains images.

I’ve updated my repository with the current code (https://bitbucket.org/noesteijver/frontity/src/master/).

Hi @dominique

You may need to prefetch the items using a beforeSSR action, so you could try adding something like this to your theme’s index.js file:

beforeSSR: async ({actions}) => {
   await actions.source.fetch("/acf/options");
}

Here is the documentation for beforeSSR.

Hi @mburridge,

This is my beforeSSR, the fetch that you mentioned was already in it:

...
beforeSSR: async ({ state, actions }) => {
        // getNameAndDescription,
        await Promise.all(
          [
            actions.source.fetch("acf/options"),
            actions.source.fetch("acf/identity"),
            actions.source.fetch("getWPConfig"),

            state.theme.templates.map((slug) =>
              actions.source.fetch(`/wp_template_part/${slug}`)
            ),
          ]
        );
      },
...

The ACF options are not the problem, otherwise the slides would not be visible. It’s the attachments that aren’t available to Frontity at the moment of visiting the front-page.

When visiting the blogs page, apparently they are being fetched, but not when visiting the front page. The slider will only show images that are being loaded on the blogs page, so if the image is not in one of the articles on the blogs page, they won’t show up in the front-page slider either.

@mburridge

I’m very sorry for being so rude, but do you have any more ideas about what’s going on here and how to solve it?

Hi @dominique

Sorry for the failure to communicate, I’ve cloned your repo locally and am working on trying to find a solution. I’ll let you know when I have anything to share.

1 Like

Not sure if I understood the case 100%, but if you have the ids or the slugs of the posts you want, wouldn’t be better to use something like fetch to populate the state with all the info about each post? This way, you would have any info like the title or the featured image in state.source.post[id].

Hi @SantosGuillamot,

I looked at the documentation of fetch before and tried to use it, but I couldn’t get it working the way I needed to.

After reading your post I tried one more time and low and behold: it worked! The posts are now being fetched and the images are being shown. I’m not sure what I’m doing different then before, but of course there must be a difference.

Thanks for encouraging me to try it once more!

For future reference for others, here’s the code for my slider:

const Slider = ({ state, actions }) => {
   const options = state.source.get("acf/options");
   const sliderItems = options.acf.home_slider_items;

   let slides = [];
   for (let i = 0; i < sliderItems.length; i++) {
      const postLinkPrefix = (sliderItems[i].post_type != 'post') ? '/' + sliderItems[i].post_type : '';
      const postLink = postLinkPrefix + "/" + sliderItems[i].post_name;

      useEffect(() => {
         actions.source.fetch(postLink);
      }, []);

      const dataPost = state.source.get(postLink);

      const featuredImageID = (dataPost.isReady) ? state.source[sliderItems[i].post_type][sliderItems[i].ID].featured_media : null;

      slides.push(<Slide href={postLinkPrefix + "/" + sliderItems[i].post_name} style={Object.assign({}, styles.slide, styles['slide' + i % 3])}>slide n°{i}: {sliderItems[i].post_title}<FeaturedMedia id={featuredImageID} /></Slide>)
   }

   return (
      <AutoPlaySwipeableViews enableMouseEvents>
         {slides}
      </AutoPlaySwipeableViews>
   );
}
4 Likes

Awesome @dominique, glad you managed to get this working in the end. :+1:

2 Likes