I'm using Contentful as the source for pages and posts. For a single page, I would like to use something like onCreatePage to insert one or perhaps several React components into a certain point in the page's HTML. The insertion point is marked by an empty span with an ID. In order to use getElementByID and set its innerHTML, however, I need a way to get at the page's markup from onCreatePage's page object. Is that possible?
And while we're on the subject, it would be really cool if the onCreatePage documentation could be expanded.
Here's my current gatsby-config.js:
const path = require('path')
const pageTemplate = path.resolve('./src/templates/page.js')
const postTemplate = path.resolve('./src/templates/post.js')
const blogCategoryTemplate = path.resolve('./src/templates/blogCategory.js')
const contentfulQuery = contentType => `
{
content: allContentful${contentType} {
edges {
node {
parent {
id
}
slug
}
}
}
}
`
const pageSets = [
{ query: contentfulQuery(`Page`), component: pageTemplate },
{ query: contentfulQuery(`Post`), component: postTemplate },
{ query: contentfulQuery(`Category`), component: blogCategoryTemplate },
]
const pagePath = node => {
switch (node.parent.id) {
case `Post`:
return `/blog/` + node.slug
case `Category`:
return `/blog/category/` + node.slug
default:
return node.slug
}
}
exports.createPages = ({ graphql, boundActionCreators }) => {
const { createPage } = boundActionCreators
pageSets.forEach(async ({ query, component }) => {
const response = await graphql(query)
if (response.errors) {
console.error(response.errors)
throw new Error(response.errors)
}
response.data.content.edges.forEach(({ node }) => {
createPage({
path: pagePath(node),
component,
context: {
slug: node.slug,
},
})
})
})
}
You could do this using the onCreateNode API to add the new content to your Contentful nodes. This is typically how transformer plugins work. An example of this is the gatsby-transformer-remark which creates markdownRemark nodes from markdown files.
Check out the onCreateNode docs for a bit more info. A lot of the examples and plugins in this repo implement onCreateNode, which can be a handy reference.
PRs that improve any part of the docs are always very welcome! Particularly if you're working through an area and feel that there's some vital info missing.
@m-allanson Thanks for the tip!
I tried the following
exports.onCreateNode = async ({ node, loadNodeContent }) => {
if (node.path === `/standorte`) {
console.log('node :', node)
const nodeContent = await loadNodeContent(node)
console.log('nodeContent :', nodeContent)
}
}
which indeed gave me the expected node
node : { layout: 'index',
jsonName: 'standorte.json',
internalComponentName: 'ComponentStandorte',
path: '/standorte',
matchPath: undefined,
component: '/Users/Janosh/Sites/sbs/src/templates/page.js',
componentChunkName: 'component---src-templates-page-js',
context: { slug: 'standorte' },
pluginCreator___NODE: 'Plugin default-site-plugin',
pluginCreatorId: 'Plugin default-site-plugin',
componentPath: '/Users/Janosh/Sites/sbs/src/templates/page.js',
id: 'SitePage /standorte',
parent: 'SOURCE',
children: [],
internal:
{ type: 'SitePage',
contentDigest: 'c7e186dbbf6979360b012ccb27679ff3',
description: 'Your site\'s "gatsby-node.js"',
owner: 'internal-data-bridge' } }
Problem is, once it reaches loadNodeContent, I get the error:
nodeContent : Promise {
_bitField: 17825792,
_fulfillmentHandler0:
Error: Could not find function loadNodeContent for plugin internal-data-bridge
at /Users/Janosh/Sites/sbs/node_modules/gatsby/dist/redux/index.js:141:15
at Promise._execute (/Users/Janosh/Sites/sbs/node_modules/bluebird/js/release/debuggability.js:303:9)
...
Any advice on how to proceed would be great!
Due to the high volume of issues, we're closing out older ones without recent activity. Please open a new issue if you need help!
Most helpful comment
@m-allanson Thanks for the tip!
I tried the following
which indeed gave me the expected node
Problem is, once it reaches
loadNodeContent, I get the error:Any advice on how to proceed would be great!