Skip to content

Paragraphs

This guide covers how to add Paragraphs to a content type in Drupal and then expose them to the GraphQL schema to be consumed by a front end application.

Additional information about Paragraphs can be found on the Concepts documentation.

To get started, you need a Drupal instance with the following modules installed and enabled

If you’re using the drupal-decoupled-graphql-basic-recipe recipe. You’ll need to install the Paragraphs module:

Terminal window
ddev composer require 'drupal/paragraphs'

Next, enable the Paragraphs module.

Terminal window
ddev drush en paragraphs

Once you have the Paragraphs module enabled, you can add a new Paragraph type under the Structure > Paragraph types > Add paragraph type section. As an example you can name it Rich Text.

Now you’ll add a new field to the Paragraph type you created in the previous step. Click on Create a new field, select Plain text and name it Name and hit Save settings.

Now you’ll add another field to the Paragraph type. Click on Create a new field, select Formatted text name it Description, set it as Text (formatted, long) and in the Allowed text format select Full HTML and hit Save settings.

To add a new Paragraph field to the Article content type, navigate to the content type’s manage fields page: https://drupal-decoupled.ddev.site/admin/structure/types/manage/article/fields

Click on the Create a new field button and select the Paragraphs field type. Name it Components.

Scroll down and make sure to select the Rich Text Paragraph type created on the Add a new Paragraph type section. Finally, click on the Save Settings button to save the field.

Expose the Paragraph field to the GraphQL schema

Section titled “Expose the Paragraph field to the GraphQL schema”

By default new types are not exposed to the GraphQL schema. So in order to expose the Rich Text Paragraph type:

Navigate to the GraphQL Compose configuration https://drupal-decoupled.ddev.site/admin/config/graphql_compose, under the Schema tab click on Paragraph > Rich Text and enable the following toggles:

  • Enable GraphQL
  • Enable single query
  • Enable edge query

Under Paragraph > Rich Text > Fields section expand the Name and Description fields and enable the “Enable field” toggle.

Lastly, navigate to Content > Article > Fields and expand the Components field, make sure to enable the “Enable field” toggle.

Hit Save configuration.

Navigate an edit an existing Article under the Content section here: https://drupal-decoupled.ddev.site/admin/content.

Add a new Paragraph by clicking on the Add Rich Text button under the Components section.

Fill Name with “First Paragraph” and Description with “This is the first Paragraph”. Feel free to add bullet items. Then click on the Save button, to save the Paragraph and update the Article.

If you came from the React Router Guide, you should have a splat route that uses the NodeArticleFragment. Update the app/graphql/fragments/node.ts file to fetch the components Paragraph for the Article; place the suggested query changes under NodeArticleFragment right after the metatag field.

app/graphql/fragments/node.ts
export const NodeArticleFragment = graphql(
`
fragment NodeArticleFragment on NodeArticle {
...
metatag {
...MetatagFragment
}
// highlight-addition-start
components {
... on ParagraphRichText {
__typename
name
description {
value
}
}
}
// highlight-addition-end
body {
processed
}
}
`,
[MediaImageFragment, UserFragment, MetatagFragment],
);

Now that the query is updated to fetch the Paragraph components, you can render them in the page. Update app/integration/node/NodeArticle.tsx to handle the new components data.

app/integration/node/NodeArticle.tsx
export default function NodeArticleComponent({
node,
}: NodeArticleComponentProps) {
// highlight-addition-start
const { title, body, image, author, changed, components } = readFragment(
// highlight-addition-end
NodeArticleFragment,
node,
);
...
return (
<>
<Article
title={title}
content={body.processed.toString()}
author={resolveUser(author)}
image={resolveMediaImage(image)}
publishDate={Number(changed.timestamp)}
/>
// highlight-addition-start
{components &&
components.map((component) => {
if (component.__typename === "ParagraphRichText") {
return (
<div key={component.name} className="mb-6">
<h2 className="text-4xl font-bold tracking-tighter leading-none mb-6 text-left">
{component.name}
</h2>
<div
className="max-w-sm lg:max-w-4xl mx-auto text-lg"
dangerouslySetInnerHTML={{
__html: component.description.value,
}}
/>
</div>
)
}
})
}
// highlight-addition-end
</>
);
}

Now, the new Paragraph component should render in the page, you can check by visiting the page in the browser.