Open logemann opened 3 years ago
Fields meta data is always empty on the first render. You have to wait for the author data to be present since the call is async
. Here's an example of how we do it with your config. Basically you need a bunch of if statements to get the required data.
// BlogPostPreview.js
const BlogPostPreview = ({ entry, fieldsMetaData, widgetFor, getAsset }) => {
const props = entry.toJS().data;
const relations = fieldsMetaData.toJS();
const selectedAuthorEmail = props.author; // save the selected author email
// remove the author email from the props (this makes it easier to handle
// the preview since the preview is expecting an author object
props.author = {};
let isCMSAuthorLoading; // Initialize this as undefined (see the component for why)
// Only go into a loading state if the user has selected an author from the
// relation dropdown
if (selectedAuthorEmail && selectedAuthorEmail.length) {
isCMSAuthorLoading = true;
}
// This requires some knowledge of how the fieldsMetaData object is structured.
if (relations) {
const authorRelationObj = relations.author;
if (authorRelationObj) {
const allAuthors = Object.values(authorRelationObj.authors);
if (allAuthors.length) {
// authorRelationObj.authors will have all of the authors the
// were selected or previously selected during the user's
// interaction with this blog post within the current session.
// So we need to find the correct author.
const author = allAuthors.find(({ email }) => email === selectedAuthorEmail);
if (author) {
isCMSAuthorLoading = false;
// set the found author relation "in-place" within the
// entry's props
props.author = author;
}
}
}
}
return (
<BlogPost isCMSPreview isCMSAuthorLoading={isCMSAuthorLoading} {...props} />
)
};
// BlogPost.js
const BlogPost = ({ isCMSPreview, isCMSAuthorLoading, author, ...otherBlogPostProps }) => {
// The `author` prop is now an object at all times so we can always do this spread `...` operator
let authorComponent = <AuthorComponent {...author} />;
// Do some logic using the `isCMSAuthorLoading` prop to determine if the
// author relation data has started/finished loading and render some basic
// informational components if the info isn't available yet.
if (isCMSPreview) {
if (isCMSAuthorLoading === false) {
authorComponent = <AuthorComponent {...author} />;
} else if (isCMSAuthorLoading === true) {
authorComponent = (
<div style={{ margin: "40px 0" }}>
{/* Render a loading component if you have one */}
{/* <LoadingIcon /> */}
<p style={{ textAlign: "center" }}>
Author Loading. Please Wait...
</p>
</div>
);
} else if (isCMSAuthorLoading === undefined) {
authorComponent = (
<div style={{ margin: "40px 0" }}>
<p style={{ textAlign: "center", color: "red" }}>
Select an author from the author dropdown
</p>
</div>
);
}
}
return (
<div className="blog-post">
{authorComponent}
-- Content --
</div>
)
}
You can also replace the .find()
with a .filter()
and a .every()
if your relation
widget is set to multiple: true
.
Describe the bug fieldsMetaData attribute is empty on registerPreviewTemplate() handler.
To Reproduce register own PreviewTemplate and print out the incoming data.
Expected behavior fieldsMetaData with data about the collection and more importantly about the "relation" collections. Thats the reason why i need it.
Screenshots
Applicable Versions: netlify-cms-app 2.14.10 netlify-cms-core 2.36.9 together with latest Gatsby.
CMS configuration
Additional context
As written. For preview reason i need the authors image, which is stored in the "relation" collection. The only way to get those related attributes is via fieldsMetaData according to Docs.
One more note to the docs at https://www.netlifycms.org/docs/customization/ . I appreciate the specific section about MetaData but the example is pretty non-selfexplaining cause no one knows the data model behind this example. I mean, the obfuscation resulting by using Immutable.js is ok as long as the docs make it clear what kind of object "data" is in data.author. To me this snippet wouldnt even work because of that phantom "data" object.
Then in the document its written: "react_component: A React component that renders the collection data. Six props will be passed to your component during render:"
But with fieldsMetaData object, its 7 isnt it? Its not mentioned there as a bullet point.
I think tons of issues could be prevented by having proper API docs.