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?
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:
- Visit: https://frontity-test-98427dzn9.vercel.app/
- Then click āBlogsā in the nav bar;
- 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?
1 Like
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>
);
}
5 Likes
Awesome @dominique, glad you managed to get this working in the end.
2 Likes
Hi guys,
Iām also trying to get data from an ACF Post Object field of a Custom Post Type.
I have this Post Object field on the Homepage. This field lets display two posts from a custom post type.
I am not sure how to retrieve the data from these two posts. The custom post type is called ācase_studiesā.
I have added the postTypes reference in frontity.settings.js, like so
"packages": [
{
"name": "wwt-theme",
},
{
"name": "@frontity/wp-source",
"state": {
"source": {
"url": "http://wwt.local",
"homepage": "/home"
},
"postTypes": [
{
"type": "case_studies",
"endpoint": "case_studies",
"archive": "case_studies"
}
]
}
},
Now, in my CaseStudies component I can console.log the Post Object field, which returns this array
I need to get the data from the post with post_type: ācase_studiesā and id of 89 but I canāt figure out how to do that.
This is what Iāve tried so far but with no success.
<CaseStudiesWrapper>
{caseStudies && caseStudies.map((caseStudy, index) => {
// const caseStudyType = caseStudy.post_type;
const caseStudyID = `/case_studies/${caseStudy.ID}`;
const caseStudyData = state.source.get(caseStudyID);
useEffect(() => {
actions.source.fetch(caseStudyID);
}, []);
return (
<CaseStudy key={index}></CaseStudy>
);
})}
</CaseStudiesWrapper>
Am I missing something and/or what am I doing wrong? Many thanks!
Hi all,
Iāve managed to resolve my own issue. It was easier than I thoughtā¦! In case anyone else has the same problem I post the answer below.
Iāve put the postTypes arguments in the wrong place, they should go under āsourceā and not under āstateā, like so
"state": {
"source": {
"url": "http://wwt.local",
"homepage": "/home",
"postTypes": [
{
"type": "case_studies",
"endpoint": "case_studies",
"archive": "/case_studies"
}
]
},
}
and I can retrieve the individual posts like so
<CaseStudiesWrapper>
{caseStudies && caseStudies.map((caseStudy, index) => {
const caseStudyType = caseStudy.post_type;
const caseStudyData = state.source[caseStudyType][caseStudy.ID];
return (
<CaseStudy key={index}></CaseStudy>
);
})}
</CaseStudiesWrapper>