I have created some custom fields for /blog page and want to show those fields and featured_media for on this page.
I just do egā¦
const data = state.source.get(state.router.link);
const post = state.source[data.type][data.id];
const foo = post.acf.foo
console.log data and post and youāll see what information is available
For featured media Iām sure thereās an examples in Mars themeā¦ look for the Boolean in the settings file and check how thatās implemented in the code
for individual post and pages data.id exists but for /blog page (by making the page as blog page in wordpress settings) data.id doesnāt exist
const data = state.source.get('/blog');
const page = state.source[data.type][data.id];
so I canāt get page or acf prop from it
This is what I get from state.source.get('/blog')
isArchive: true
isFetching: false
isPostArchive: true
isPostTypeArchive: true
isReady: true
items: [post objects]
link: "/blog/"
next: "/blog/page/2/"
page: 1
query: {}
route: "/blog/"
total: 51
totalPages: 6
type: "post"
So what are your acf fields attached to? Surely individual items in the blog?
The problem youāre having is caused by a limitation in the REST API of WordPress (or actually, a limitation of WordPress in general).
When querying /blog/
you will not get a post or page, but instead a collection of posts. WordPress does not know that itās an actual page (even though it exists), so instead will return the contents of the archive.
I guess the only solution is to do a second fetch to ACF directly to retrieve the data from that page.
You could maybe do something like what I did here and create a page called eg /blog_page and manually 404 the route in the browser, but use it to get data over REST
Yes frontity only gives the collection of posts when doing state.source[data.type]
. I am not sure why data.id
is missing for /blog
only.
As the wordpress rest endpoint is giving both the featured_media
and acf
fields but are missing when getting via frontity.
/blog
is set to be postsPage
but it is a page. Frontity should also return id for this page so we can get the page details just like other pages.
Because an archive page is not a real page, so it doesnāt have a page/post id. Even when you have set a page in WP.
So itās normal behavior in WordPress.
But when listing the pages using wp-rest apis, Iām getting the id, featured_media, acf
for the /blog, like this
{
"id":64,
"slug":"blog",
"status":"publish",
"type":"page",
"title":{
"rendered":"Blog"
},
"author":1,
"featured_media":1637,
"acf":{
"title":"Blog"
}
}
My doubt is that why is it missing in frontity source?
Because, as I explained before, when you get the posts archive (/blog
) WordPress will not return the page.
The request you sent is:
/wp-json/wp/v2/pages?slug=/blog
This will obviously return the content of the āblogā page, but does not return anything else (like the posts it should show.
The request that is actually done:
/wp-json/wp/v2/posts
This will return all the posts which is the same as WordPress does on the archive. And since you set ā/blogā as the posts archive URI, it will do this request by default (as it should).
So itās not a bug or missing feature in Frontity, itās how WordPress works and how Frontity implemented it to return the exact same results.
Got it. Thank you for the explanation
There is a solution though and that is through creating a custom handler.
Here are the general steps:
- Change the postsPage in frontity.settings to something else
- Create a handler for /blog/
- Get /blog by using
endpoint: 'pages',
params: {
slug: 'blog',
_embed: true,
},
});
- Get all your blog posts by
await api.get({
endpoint: 'posts',
params: {
per_page: 100,
_embed: true,
},
});
- Then build your own state.source.data by setting isPostArchive to true etc.
I can share more in detail if anyone is curious.
Here are some links that might help:
Here is the handler. Not tested!
const blogHandler = {
pattern: '/blog/',
priority: 5,
func: async ({link, params, state, libraries}) => {
const {api, populate, getTotalPages} = libraries.source;
// Get the Blog Page
// 1. search id in state or get the entity from WP REST API
const {route, query} = libraries.source.parse(link);
const routeData = state.source.get(route);
if (!routeData.id) {
//console.log(routeData);
// Get the page
let response = await api.get({
endpoint: 'pages',
params: {
slug: 'blog',
_embed: true,
},
});
const blogPage = await populate({
response,
state,
});
console.log("Blog Page", blogPage);
}
// 2. Get the Blog List
let response = await api.get({
endpoint: 'posts',
params: {
per_page: 100,
_embed: true,
},
});
const firstItems = await populate({
response,
state,
});
const pages = getTotalPages(response);
const requests = [];
// Get the next pages
for (let page = 2; page <= pages; page++) {
requests.push(
api.get({
endpoint: 'posts',
params: {
per_page: 100,
page,
_embed: true,
},
}),
);
}
const responses = await Promise.all(requests);
const newItems = await Promise.all(
responses.map((response) => populate({state, response})),
);
const items = firstItems.concat(newItems);
// 4. add data to source
const currentPageData = state.source.data['/blog/'];
const postData = {
isPostType: true,
isPostArchive: true,
type: 'page',
items,
};
Object.assign(currentPageData, postData);
},
};
export default blogHandler;