Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add another node as a field on a node #6041

Closed
snirp opened this issue Jun 20, 2018 · 7 comments
Closed

Add another node as a field on a node #6041

snirp opened this issue Jun 20, 2018 · 7 comments
Labels
type: question or discussion Issue discussing or asking a question about Gatsby

Comments

@snirp
Copy link

snirp commented Jun 20, 2018

Is it possible to add a different node as a field on a node? In my case I have MarkdownRemark nodes, that I want to extend with a childImageSharp node under fields.

Some background:
The markdown node constitutes a blog post and it each blog post has a "hero" image. This is identified as a file named "hero(...)" in the same dir as the markdown post. I can currently get the hero image in the blog-post template, by passing a "regex" string in the context. Something like "/my-blogpost\/hero/".

It seems more powerful to simply add the ImageSharp node directly to the field, so I can directly access it anywhere I need it. Does graphql / gatsby allow for that?

Sorry for adding a question here, that I can probably solve with some work, but it would really save me some time. I promise the update this post with a code sample, once I get it to work.

@snirp
Copy link
Author

snirp commented Jun 20, 2018

Quick update: it is possible to set another node as a field. Did a quick test by setting the parentNode as a field.

Unfortunately the graphql function is not available in the onCreateNode api. Looks like I have to use another api or use getNodes to somehow identify the image node.

@pieh pieh added the type: question or discussion Issue discussing or asking a question about Gatsby label Jun 20, 2018
@pieh
Copy link
Contributor

pieh commented Jun 20, 2018

in onCreateNode you can use createNodeField action to add field pointing to your image:

exports.onCreateNode = ({ node, getNode, actions }) => {
    const { createNodeField } = actions;
    if (node.internal.type === `MarkdownRemark`) {
        createNodeField({
            node,
            name: `heroImage`,
            value: `./hero-something.jpg`, // adjust as needed here - this need to be relative path to image from your markdown file
        });
    }
};

this will create fields object in MarkdownRemark nodes and there you will have heroImage that Gatsby will automatically convert to File node which will have childImageSharp if you have sharp plugins installed and path in that field is correct

@snirp
Copy link
Author

snirp commented Jun 20, 2018

Ok wow, just to double check: Gatsby will always try to convert a field value to a file node (if the string is a valid path?).

I tried to do it "manually" with getNodes(), but the ImageSharp nodes do not appear in GetNodes(). Is that expected behavior?

exports.onCreateNode = ({ getNodes }) => {
  //...
      const heroNode = getNodes().find(
        node =>
          node.internal.type === `ImageSharp` // && match path in id or parentnode with regex
      )
     console.log(heroNode)  // undefined
};

@pieh
Copy link
Contributor

pieh commented Jun 20, 2018

Ok wow, just to double check: Gatsby will always try to convert a field value to a file node (if the string is a valid path?).

if field is string (or array of string) and it looks like a path, Gatsby will try to find matching File node (if you have images in same directory as markdown files you don't need anything more - if you would try to point to files/images that are not covered by your gatsby-source-filesystem config, then it wouldn't work and you would need to add directory with images to gatsby-config.js)

--edit:
If you are interested you can look here how it's done https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby/src/schema/types/type-file.js#L117

I tried to do it "manually" with getNodes(), but the ImageSharp nodes do not appear in GetNodes(). Is that expected behavior?

I think this might be order of creation of nodes issue here - we call onCreateNode as we go and sometimes File node for file you are looking for (and consequently ImageSharp child of that File node) might just not be created yet

@snirp
Copy link
Author

snirp commented Jun 20, 2018

if field is string and it looks like a path, Gatsby will try to find matching File node

Is that documented somewhere? I guess this does not allow for regex or wildcard matching...

I think this might be order of creation of nodes issue here

That was my guess too. Is there a way to get around this: another API like afterCreateNodes? This looks real fragile and there are several blog posts advertising this very use of getNodes() inside onCreateNode.

ps, Thanks a lot for the help. My initial issue was resolved. Closed the issue.

@tejedamiguel6
Copy link

Sorry for bothering anyone on here with this question. I am currently having an issue calling onCreateNode twice. Does anyone know how to do so? for example i have if(node.internal.owner === 'gatsby-source-drupal)
/// do stuff here

But i need to call it again so that i can create a new field on my menu, but it throws an error.

@CanRau
Copy link
Contributor

CanRau commented Mar 6, 2020

@tejedamiguel6 Not sure what you try to achieve, could you elaborate a little bit more what your goal is?
Why do you need to call it again?

Edit: Or have you already solved it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: question or discussion Issue discussing or asking a question about Gatsby
Projects
None yet
Development

No branches or pull requests

4 participants