Drupal News

TomThorp.me Blog: Mismatched Entity Error

Main Drupal Feed - Mon, 11/04/2019 - 13:06
If you are getting a "Mismatched entity and/or field definitions" error in your Drupal status page, then this maybe the solution you are looking for.

Jacob Rockowitz: Webform module supports creating custom elements using HTML and SVG markup

Main Drupal Feed - Mon, 11/04/2019 - 12:24

Problem

The Webform module for Drupal 8 provides support for basic, advanced, and composite inputs/elements. Developers can also create custom elements and composites via code. Sometimes end-users need an interactive visual mechanism to select a complex option like a map location. The Image select element is limited to allowing users to select horizontally-aligned images.

HTML5 and SVG allow designers and site builders to build visually rich and interactive elements. To convert rich interactive HTML/SVG elements into a form input, there needs to be some PHP and JavaScript glue code that captures a user's selection and sets it as a webform submission value.

Besides capturing the end-users selection, the PHP and JavaScript code must also ensure that the interactive HTML/SVG element is accessible to users with disabilities.

Solution

Concept

The general concept for creating a custom 'options' element' is to allow site builders to provide HTML/SVG markup that is dynamically converted into a select-able and accessible Webform element.

Below is a straightforward example of some HTML markup that can be enhanced.

SVG support requires the same data-id and data-name attributes being added to the HTML markup. Below is an example of a single clickable element in SVG.

Implementation

The HTML/SVG markup must provide an option value or text attribute that can be used to create a list of available options. The default recommended 'value' attribute names are 'data-option-value', 'data-value', 'data-id', or 'id'. The default recommended 'text' attribute names are 'data-option-text', 'data-text', 'data-name', 'name', or 'title'. The Webform module uses these value/text attribute names to parse and detect the custom element's available...Read More

Jacob Rockowitz: Webform module supports creating custom elements using HTML and SVG markup

Main Drupal Feed - Mon, 11/04/2019 - 12:24

Problem

The Webform module for Drupal 8 provides support for basic, advanced, and composite inputs/elements. Developers can also create custom elements and composites via code. Sometimes end-users need an interactive visual mechanism to select a complex option like a map location. The Image select element is limited to allowing users to select horizontally-aligned images.

HTML5 and SVG allow designers and site builders to build visually rich and interactive elements. To convert rich interactive HTML/SVG elements into a form input, there needs to be some PHP and JavaScript glue code that captures a user's selection and sets it as a webform submission value.

Besides capturing the end-users selection, the PHP and JavaScript code must also ensure that the interactive HTML/SVG element is accessible to users with disabilities.

Solution

Concept

The general concept for creating a custom 'options' element' is to allow site builders to provide HTML/SVG markup that is dynamically converted into a select-able and accessible Webform element.

Below is a straightforward example of some HTML markup that can be enhanced.

SVG support requires the same data-id and data-name attributes being added to the HTML markup. Below is an example of a single clickable element in SVG.

Implementation

The HTML/SVG markup must provide an option value or text attribute that can be used to create a list of available options. The default recommended 'value' attribute names are 'data-option-value', 'data-value', 'data-id', or 'id'. The default recommended 'text' attribute names are 'data-option-text', 'data-text', 'data-name', 'name', or 'title'. The Webform module uses these value/text attribute names to parse and detect the custom element's available...Read More

Web Wash: Getting Started with React in Drupal 8

Main Drupal Feed - Mon, 11/04/2019 - 12:00

If you’ve done any web development in the last couple of years, then I’m sure you noticed that JavaScript libraries and frameworks have become popular. The three that come to mind are React, Vue.js, Angular but there are many, many more.

These libraries and frameworks are great for building complex JavaScript applications. Also, being written in JavaScript means they can easily be embedded into a Drupal site.

In this tutorial, I’ll show you how to embed and compile a React application using two methods: Lavavel Mix and Webpack. If you want to use React then you’ll realize very quickly that you can’t just write JavaScript and have it work out-of-the-box, it needs to be compiled. That’s why I’ll show you two ways you can compile React locally without using a CDN.

This tutorial is targeted towards developers who know how to create a Drupal module, use the npm command and know basic React.

A copy of all the code can be found at https://github.com/WebWash/ww_react_examples.

Web Wash: Getting Started with React in Drupal 8

Main Drupal Feed - Mon, 11/04/2019 - 12:00

If you’ve done any web development in the last couple of years, then I’m sure you noticed that JavaScript libraries and frameworks have become popular. The three that come to mind are React, Vue.js, Angular but there are many, many more.

These libraries and frameworks are great for building complex JavaScript applications. Also, being written in JavaScript means they can easily be embedded into a Drupal site.

In this tutorial, I’ll show you how to embed and compile a React application using two methods: Lavavel Mix and Webpack. If you want to use React then you’ll realize very quickly that you can’t just write JavaScript and have it work out-of-the-box, it needs to be compiled. That’s why I’ll show you two ways you can compile React locally without using a CDN.

This tutorial is targeted towards developers who know how to create a Drupal module, use the npm command and know basic React.

A copy of all the code can be found at https://github.com/WebWash/ww_react_examples.

Web Wash: Getting Started with React in Drupal 8

Main Drupal Feed - Mon, 11/04/2019 - 12:00

If you’ve done any web development in the last couple of years, then I’m sure you noticed that JavaScript libraries and frameworks have become popular. The three that come to mind are React, Vue.js, Angular but there are many, many more.

These libraries and frameworks are great for building complex JavaScript applications. Also, being written in JavaScript means they can easily be embedded into a Drupal site.

In this tutorial, I’ll show you how to embed and compile a React application using two methods: Lavavel Mix and Webpack. If you want to use React then you’ll realize very quickly that you can’t just write JavaScript and have it work out-of-the-box, it needs to be compiled. That’s why I’ll show you two ways you can compile React locally without using a CDN.

This tutorial is targeted towards developers who know how to create a Drupal module, use the npm command and know basic React.

A copy of all the code can be found at https://github.com/WebWash/ww_react_examples.

JD Does Development: Using Drupal Blocks in a Decoupled GatsbyJS Application

Main Drupal Feed - Sun, 11/03/2019 - 18:40
Using Drupal Blocks in a Decoupled GatsbyJS Application jflynn Sun, 11/03/2019 - 12:40

One of the most useful components of Drupal is the Block system. This system allows for pieces of content to be created and reused throughout a site in various regions of the page structure. You can also select which bundles or content types this piece of content should appear on, making it so that a blog post gets a certain Call to Action section while an article gets something similar, but different.

When we use GatsbyJS for a decoupled front-end solution with a Drupal back-end, we lose out on quite a bit, if not everything, that the theme layer of Drupal provides. This means that Drupal regions mean nothing to Gatsby, nor does block placement. In fact, any functionality that would go into a .theme file is no longer available on the Drupal side.

Before I get into the "how" of using Drupal blocks in Gatsby, I want to cover a little bit of the "why".

Why Use Drupal Blocks for Content in a Gatsby Front End?

The main advantage of blocks in Drupal is that the content is created in one place, but can be placed in several spots. I have worked with solutions that use Paragraphs (from the Paragraphs contrib module) for similar functionality, but the problem remains where the content needs to be recreated on every new parent entity. For example, I can create a Call to Action (CTA) Paragraph and place fields that reference them on every content type, but the Paragraphs themselves remain separate. A Paragraph is more like a collection of fields to be filled out than a reusable entity, and that's okay.

In contrast, a Block can be created in one place, usually using the Block UI, and the content of the Block remains the same no matter where it is placed. A CTA block on a blog post will have identical content to the CTA block on an article. This makes content changes extremely fast compared to having to update every article and blog post if the wording or link need to change.

It is entirely possible to create these types of entities in Gatsby by defining a reusable component, however the editing experience doesn't really pan out. It may require a developer to go in and edit a React component, adding a middle-person to the process. Using reusable Drupal blocks can save time and budget when set up appropriately.

How to Use Drupal Blocks for Content in a Gatsby Front End

This section is going to make a few assumptions.

  1. You have a basic understanding of Gatsby and React components.
  2. You understand the Drupal theme layer.
  3. You have a basic understanding of the Drupal block system.
  4. Your decoupled application is already setup and pulling content from Drupal (not necessary, but it helps if you can try it out)
  5. You have the JSON:API module enabled on Drupal
  6. You're sourcing content from Drupal.

If you're having problems with any of these, feel free to reach out to me on Drupal Slack, I go by Dorf there.

Now the "how".  We're going to start by creating a Custom Block Type. Let's keep going with the CTA theme and call it "CTA Block". We do this by logging into our site as someone with permissions to access the Block UI and going to admin/structure/block/block-content/types. Once there, select "Add custom block type".

Let's label this CTA Block and begin creation. After we create it, we need to add some fields, so let's add the following fields:

  • CTA Heading
    • A plain text field, max 255 chars
  • CTA Link
    • A Link field using URL and label, internal and external links, Label required.
  • CTA Content Types
    • This is the field that will make all the difference. Create this field as Reference: Other... to begin with.
    • Label it CTA Content Type.
    • Under "Type of entity to reference" choose "Content type" from the select list, under Configuration.
    • Set unlimited cardinality.
    • Go through the remaining screens to create this field. Once you're back on the field list, select "Manage form display"
    • From here, we're going to change the widget from Autocomplete to Check boxes/radio buttons.
    • Save your changes

Now we're going to create a new block using this Custom Block Type. When we create the block under block/add/cta_block the form should look something like this:

Now, add whatever text you want to the fields, but only select a single content type in the CTA Content Type field.  Save the block and spin up your Gatsby dev environment. We're going to switch over there for a bit.

Let's fire up our develop environment and take a look at GraphiQL to see what we have going on.

As you can see, we now have access to allBlockContentCtaBlock in GraphiQL, but what are we going to do with it? Well, we are first going to create the CTA Block React component. We'll do that by creating the file src/components/blocks/CtaBlock.js and adding the following:

import React from 'react' import { graphql } from 'gatsby' const CtaBlock = ({ data }) => { return CTA Heading

CTA Text goes here and here and here.

Link Text } export default CtaBlock

This is pretty simple and doesn't include anything having to do with our GraphQL query yet, but we have the structure in place. Now, let's look at the data we can pull from GraphQL. We want to get the heading, body, link, and content type, so our query is going to look something like this:

query MyQuery { allBlockContentCtaBlock { nodes { field_cta_heading field_cta_link { title uri } body { value } relationships { field_cta_content_type { name } } } } }

Which will give us back:

{ "data": { "allBlockContentCtaBlock": { "nodes": [ { "field_cta_heading": "Heading for the CTA Block", "field_cta_link": { "title": "Learn more!", "uri": "http://google.com" }, "body": { "value": "

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Vestibulum facilisis, purus nec pulvinar iaculis, ligula mi congue nunc, vitae euismod ligula urna in dolor. Aenean massa.

\r\n\r\n

Praesent nec nisl a purus blandit viverra. Nullam nulla eros, ultricies sit amet, nonummy id, imperdiet feugiat, pede. Phasellus dolor.

\r\n" }, "relationships": { "field_cta_content_type": [ { "name": "Blog Post" } ] } } ] } } }

Perfect! Now I want you to notice a couple of things here. First, we're querying ALL of the CTA blocks here. Second, we're using the content type in the query. Let's get this into our component. Add in the query to our CtaBlock.

import React from 'react' import { graphql } from 'gatsby' const CtaBlock = ({ data }) => { return CTA Heading

CTA Text goes here and here and here.

Link Text } export default CtaBlock export const CtaBlockQuery = graphql` allBlockContentCtaBlock { nodes { field_cta_heading field_cta_link { title uri } body { value } relationships { field_cta_content_type { name } } } }`

But wait, this isn't a page template, and it shouldn't be. What's the problem then? We have a query in a non-page template, and that's not good. What we need to do is figure out which of our templates are going to use this block and add it in there. Since we chose to have the block show on the blog post content type, we're going to use the blog post template. This will probably differ for your setup.

Let's open up our page template and take a look:

import React from 'react' import { graphql } from 'gatsby' import Layout from '../layouts' const BlogPostTemplate = ({ data }) => { const blogBody = data.nodeBlogPost.body.value return {data.nodeBlogPost.title} {data.nodeBlogPost.body.value} } export default BlogPostTemplate export const query = graphql` query($BlogPostID: String!){ nodeBlogPost(id: { eq: $BlogPostID }) { id title body { processed } } } `

Now let's update this to have the block appear.

import React from 'react' import { graphql } from 'gatsby' import Layout from '../layouts' import CtaBlock from '../blocks/CtaBlock' const BlogPostTemplate = ({ data }) => { const blogBody = data.nodeBlogPost.body.value return {data.nodeBlogPost.title} {data.nodeBlogPost.body.value} } export default BlogPostTemplate export const query = graphql` query($BlogPostID: String!){ nodeBlogPost(id: { eq: $BlogPostID }) { id title body { processed } } } `

But we still need to include the query for the block itself. To do this, we're going to make a few edits to both of our components. We'll start with the CtaBlock component and convert the query into a fragment that we can reuse in multiple places if need be.

import React from 'react' import { graphql } from 'gatsby' const CtaBlock = ({ data }) => { return CTA Heading

CTA Text goes here and here and here.

Link Text } export default CtaBlock export const CtaBlockQuery = graphql` fragment CtaBlockQuery on block_content__cta_block { field_cta_heading field_cta_link { title uri } body { value } relationships { field_cta_content_type { name } } }`

If you have a keen eye, you'll notice that we've removed the nodes section of the query. This is because we're now going to query for a single block. However, there is some risk to this. In the event that a content creator creates a new CTA block on Drupal for this content type instead of editing the existing one, the old one will remain in place because a single item query will only return a single item.

Now, let's move back over to our page template and use this fragment to query for our block.

import React from 'react' import { graphql } from 'gatsby' import Layout from '../layouts' import CtaBlock from '../blocks/CtaBlock' const BlogPostTemplate = ({ data }) => { const blogBody = data.nodeBlogPost.body.value return {data.nodeBlogPost.title} {data.nodeBlogPost.body.value} } export default BlogPostTemplate export const query = graphql` query($BlogPostID: String!){ nodeBlogPost(id: { eq: $BlogPostID }) { id title body { processed } } blockContentCtaBlock (relationships: {field_cta_content_types: {elemMatch: {name: {eq: "Blog Post"} } } } ){ ...CtaBlockQuery } } `

Take a look at what we've done here.  We've added in a query for the CtaBlock and we're filtering it by the content type it's attached to. After that, we're pulling in everything from the query on our component. This is exactly what we were wanting to do, but there's another step that we need to take to actually use the data on our component.

If you look at the JSX element for


you'll notice we aren't passing anything to it, so we've got to make sure it has data to work with or we're going to end up rendering nothing.  Edit that line to be 

In case you're not familiar, this is a React concept known as passing props, or properties, to a child component. We're passing the data object that was returned from our GraphQL query to the CtaBlock component so that it can use the included data. Since this is just a demo, we're passing the entire thing along, but it's easy enough to only pass the relevant parts of the object.

Now back in our CtaBlock component we can use the data to render out our block's content.

import React from 'react' import { graphql } from 'gatsby' const CtaBlock = ({ data }) => { return {data.blockContentCtaBlock.field_cta_heading}

{data.blockContentCtaBlock.field_cta_link.title} } export default CtaBlock export const CtaBlockQuery = graphql` fragment CtaBlockQuery on block_content__cta_block { field_cta_heading field_cta_link { title uri } body { value } relationships { field_cta_content_type { name } } }`

Now we have our block based on content type rendering within our content type's Gatsby template. Note that I've left out a few things that should be noted for decoupled sites. 

  1. An internal link should us the Gatsby component.
  2. Drupal needs some love to pass the correct alias over for an internal link so that it renders correctly.
  3. This is a very basic example. YMMV.

Anyway, I hope that this helps someone out there who ran into the same problems that I did. Please feel free to reach out to me on Twitter @jddoesdev, on Slack where I'm usually Dorf, or just leave a comment here if you have questions, concerns, comments, or just something nice to say.

Also, please feel free to support my efforts in speaking on mental health in tech or creating blog posts and tutorials like these by checking out my gofundme and patreon campaigns in the sidebar.

Thanks for reading!

Category Development Tags Drupal Planet Drupal GatsbyJS decoupled JSON:API Comments

JD Does Development: Using Drupal Blocks in a Decoupled GatsbyJS Application

Main Drupal Feed - Sun, 11/03/2019 - 18:40
Using Drupal Blocks in a Decoupled GatsbyJS Application jflynn Sun, 11/03/2019 - 12:40

One of the most useful components of Drupal is the Block system. This system allows for pieces of content to be created and reused throughout a site in various regions of the page structure. You can also select which bundles or content types this piece of content should appear on, making it so that a blog post gets a certain Call to Action section while an article gets something similar, but different.

When we use GatsbyJS for a decoupled front-end solution with a Drupal back-end, we lose out on quite a bit, if not everything, that the theme layer of Drupal provides. This means that Drupal regions mean nothing to Gatsby, nor does block placement. In fact, any functionality that would go into a .theme file is no longer available on the Drupal side.

Before I get into the "how" of using Drupal blocks in Gatsby, I want to cover a little bit of the "why".

Why Use Drupal Blocks for Content in a Gatsby Front End?

The main advantage of blocks in Drupal is that the content is created in one place, but can be placed in several spots. I have worked with solutions that use Paragraphs (from the Paragraphs contrib module) for similar functionality, but the problem remains where the content needs to be recreated on every new parent entity. For example, I can create a Call to Action (CTA) Paragraph and place fields that reference them on every content type, but the Paragraphs themselves remain separate. A Paragraph is more like a collection of fields to be filled out than a reusable entity, and that's okay.

In contrast, a Block can be created in one place, usually using the Block UI, and the content of the Block remains the same no matter where it is placed. A CTA block on a blog post will have identical content to the CTA block on an article. This makes content changes extremely fast compared to having to update every article and blog post if the wording or link need to change.

It is entirely possible to create these types of entities in Gatsby by defining a reusable component, however the editing experience doesn't really pan out. It may require a developer to go in and edit a React component, adding a middle-person to the process. Using reusable Drupal blocks can save time and budget when set up appropriately.

How to Use Drupal Blocks for Content in a Gatsby Front End

This section is going to make a few assumptions.

  1. You have a basic understanding of Gatsby and React components.
  2. You understand the Drupal theme layer.
  3. You have a basic understanding of the Drupal block system.
  4. Your decoupled application is already setup and pulling content from Drupal (not necessary, but it helps if you can try it out)
  5. You have the JSON:API module enabled on Drupal
  6. You're sourcing content from Drupal.

If you're having problems with any of these, feel free to reach out to me on Drupal Slack, I go by Dorf there.

Now the "how".  We're going to start by creating a Custom Block Type. Let's keep going with the CTA theme and call it "CTA Block". We do this by logging into our site as someone with permissions to access the Block UI and going to admin/structure/block/block-content/types. Once there, select "Add custom block type".

Let's label this CTA Block and begin creation. After we create it, we need to add some fields, so let's add the following fields:

  • CTA Heading
    • A plain text field, max 255 chars
  • CTA Link
    • A Link field using URL and label, internal and external links, Label required.
  • CTA Content Types
    • This is the field that will make all the difference. Create this field as Reference: Other... to begin with.
    • Label it CTA Content Type.
    • Under "Type of entity to reference" choose "Content type" from the select list, under Configuration.
    • Set unlimited cardinality.
    • Go through the remaining screens to create this field. Once you're back on the field list, select "Manage form display"
    • From here, we're going to change the widget from Autocomplete to Check boxes/radio buttons.
    • Save your changes

Now we're going to create a new block using this Custom Block Type. When we create the block under block/add/cta_block the form should look something like this:

Now, add whatever text you want to the fields, but only select a single content type in the CTA Content Type field.  Save the block and spin up your Gatsby dev environment. We're going to switch over there for a bit.

Let's fire up our develop environment and take a look at GraphiQL to see what we have going on.

As you can see, we now have access to allBlockContentCtaBlock in GraphiQL, but what are we going to do with it? Well, we are first going to create the CTA Block React component. We'll do that by creating the file src/components/blocks/CtaBlock.js and adding the following:

import React from 'react' import { graphql } from 'gatsby' const CtaBlock = ({ data }) => { return CTA Heading

CTA Text goes here and here and here.

Link Text } export default CtaBlock

This is pretty simple and doesn't include anything having to do with our GraphQL query yet, but we have the structure in place. Now, let's look at the data we can pull from GraphQL. We want to get the heading, body, link, and content type, so our query is going to look something like this:

query MyQuery { allBlockContentCtaBlock { nodes { field_cta_heading field_cta_link { title uri } body { value } relationships { field_cta_content_type { name } } } } }

Which will give us back:

{ "data": { "allBlockContentCtaBlock": { "nodes": [ { "field_cta_heading": "Heading for the CTA Block", "field_cta_link": { "title": "Learn more!", "uri": "http://google.com" }, "body": { "value": "

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Vestibulum facilisis, purus nec pulvinar iaculis, ligula mi congue nunc, vitae euismod ligula urna in dolor. Aenean massa.

\r\n\r\n

Praesent nec nisl a purus blandit viverra. Nullam nulla eros, ultricies sit amet, nonummy id, imperdiet feugiat, pede. Phasellus dolor.

\r\n" }, "relationships": { "field_cta_content_type": [ { "name": "Blog Post" } ] } } ] } } }

Perfect! Now I want you to notice a couple of things here. First, we're querying ALL of the CTA blocks here. Second, we're using the content type in the query. Let's get this into our component. Add in the query to our CtaBlock.

import React from 'react' import { graphql } from 'gatsby' const CtaBlock = ({ data }) => { return CTA Heading

CTA Text goes here and here and here.

Link Text } export default CtaBlock export const CtaBlockQuery = graphql` allBlockContentCtaBlock { nodes { field_cta_heading field_cta_link { title uri } body { value } relationships { field_cta_content_type { name } } } }`

But wait, this isn't a page template, and it shouldn't be. What's the problem then? We have a query in a non-page template, and that's not good. What we need to do is figure out which of our templates are going to use this block and add it in there. Since we chose to have the block show on the blog post content type, we're going to use the blog post template. This will probably differ for your setup.

Let's open up our page template and take a look:

import React from 'react' import { graphql } from 'gatsby' import Layout from '../layouts' const BlogPostTemplate = ({ data }) => { const blogBody = data.nodeBlogPost.body.value return {data.nodeBlogPost.title} {data.nodeBlogPost.body.value} } export default BlogPostTemplate export const query = graphql` query($BlogPostID: String!){ nodeBlogPost(id: { eq: $BlogPostID }) { id title body { processed } } } `

Now let's update this to have the block appear.

import React from 'react' import { graphql } from 'gatsby' import Layout from '../layouts' import CtaBlock from '../blocks/CtaBlock' const BlogPostTemplate = ({ data }) => { const blogBody = data.nodeBlogPost.body.value return {data.nodeBlogPost.title} {data.nodeBlogPost.body.value} } export default BlogPostTemplate export const query = graphql` query($BlogPostID: String!){ nodeBlogPost(id: { eq: $BlogPostID }) { id title body { processed } } } `

But we still need to include the query for the block itself. To do this, we're going to make a few edits to both of our components. We'll start with the CtaBlock component and convert the query into a fragment that we can reuse in multiple places if need be.

import React from 'react' import { graphql } from 'gatsby' const CtaBlock = ({ data }) => { return CTA Heading

CTA Text goes here and here and here.

Link Text } export default CtaBlock export const CtaBlockQuery = graphql` fragment CtaBlockQuery on block_content__cta_block { field_cta_heading field_cta_link { title uri } body { value } relationships { field_cta_content_type { name } } }`

If you have a keen eye, you'll notice that we've removed the nodes section of the query. This is because we're now going to query for a single block. However, there is some risk to this. In the event that a content creator creates a new CTA block on Drupal for this content type instead of editing the existing one, the old one will remain in place because a single item query will only return a single item.

Now, let's move back over to our page template and use this fragment to query for our block.

import React from 'react' import { graphql } from 'gatsby' import Layout from '../layouts' import CtaBlock from '../blocks/CtaBlock' const BlogPostTemplate = ({ data }) => { const blogBody = data.nodeBlogPost.body.value return {data.nodeBlogPost.title} {data.nodeBlogPost.body.value} } export default BlogPostTemplate export const query = graphql` query($BlogPostID: String!){ nodeBlogPost(id: { eq: $BlogPostID }) { id title body { processed } } blockContentCtaBlock (relationships: {field_cta_content_types: {elemMatch: {name: {eq: "Blog Post"} } } } ){ ...CtaBlockQuery } } `

Take a look at what we've done here.  We've added in a query for the CtaBlock and we're filtering it by the content type it's attached to. After that, we're pulling in everything from the query on our component. This is exactly what we were wanting to do, but there's another step that we need to take to actually use the data on our component.

If you look at the JSX element for


you'll notice we aren't passing anything to it, so we've got to make sure it has data to work with or we're going to end up rendering nothing.  Edit that line to be 

In case you're not familiar, this is a React concept known as passing props, or properties, to a child component. We're passing the data object that was returned from our GraphQL query to the CtaBlock component so that it can use the included data. Since this is just a demo, we're passing the entire thing along, but it's easy enough to only pass the relevant parts of the object.

Now back in our CtaBlock component we can use the data to render out our block's content.

import React from 'react' import { graphql } from 'gatsby' const CtaBlock = ({ data }) => { return {data.blockContentCtaBlock.field_cta_heading}

{data.blockContentCtaBlock.field_cta_link.title} } export default CtaBlock export const CtaBlockQuery = graphql` fragment CtaBlockQuery on block_content__cta_block { field_cta_heading field_cta_link { title uri } body { value } relationships { field_cta_content_type { name } } }`

Now we have our block based on content type rendering within our content type's Gatsby template. Note that I've left out a few things that should be noted for decoupled sites. 

  1. An internal link should us the Gatsby component.
  2. Drupal needs some love to pass the correct alias over for an internal link so that it renders correctly.
  3. This is a very basic example. YMMV.

Anyway, I hope that this helps someone out there who ran into the same problems that I did. Please feel free to reach out to me on Twitter @jddoesdev, on Slack where I'm usually Dorf, or just leave a comment here if you have questions, concerns, comments, or just something nice to say.

Also, please feel free to support my efforts in speaking on mental health in tech or creating blog posts and tutorials like these by checking out my gofundme and patreon campaigns in the sidebar.

Thanks for reading!

Category Development Tags Drupal Planet Drupal GatsbyJS decoupled JSON:API Comments

CTI Digital: How to start contributing to Drupal without code - DrupalCon Amsterdam Edition

Main Drupal Feed - Fri, 11/01/2019 - 17:24

It was during his 2015 DrupalCon Europe keynote when Dries Buytaert first discussed the ‘free-rider problem’. Dries proposed improvements to the way Drupal tracks contribution an a scale of “social capital”. This would better recognise all types of work and how contributions can lead to a bigger impact in the world.

CTI Digital: How to start contributing to Drupal without code - DrupalCon Amsterdam Edition

Main Drupal Feed - Fri, 11/01/2019 - 17:24

It was during his 2015 DrupalCon Europe keynote when Dries Buytaert first discussed the ‘free-rider problem’. Dries proposed improvements to the way Drupal tracks contribution an a scale of “social capital”. This would better recognise all types of work and how contributions can lead to a bigger impact in the world.

CTI Digital: How to start contributing to Drupal without code - DrupalCon Amsterdam Edition

Main Drupal Feed - Fri, 11/01/2019 - 17:24

It was during his 2015 DrupalCon Europe keynote when Dries Buytaert first discussed the ‘free-rider problem’. Dries proposed improvements to the way Drupal tracks contribution an a scale of “social capital”. This would better recognise all types of work and how contributions can lead to a bigger impact in the world.

wishdesk.com: Drupal more user-friendly than ever with new Help Topics module

Main Drupal Feed - Thu, 10/31/2019 - 15:09
We are happy to announce another great advancement in the Drupal user-friendliness field — the new core Help Topics module.

Sooper Drupal Themes: Digital Marketing Trends for 2020: The rise of voice search

Main Drupal Feed - Thu, 10/31/2019 - 14:01
More content for smart speakers

The steady rise of smart speakers has paved the way for new opportunities for businesses. Right now, a staggering amount of searches are done through smart speakers. What this means is that people are going to rely more and more on audio feedback. With this in mind, creating some good content and features for home speakers like Alexa and Google Home can keep you in the game. Everything is an opportunity is you work hard enough, especially adapting to new digital marketing trends.

Drupal being proven solution for headless application, is already capable of serving as a platform for you to connect your existing content directly to voice APIs.

Voice search optimization

Technology is rapidly changing and shaping the way we are interacting with our surroundings, including what digital marketing trends develop. A trend that was growing in the past year is going to grow in 2020 as well. That trend is, of course, voice search. With the rise in adoption for voice assistants and smart speakers like Alexa and Google Home, voice search has seen an incredible increase in usage over the past years. 

 

With this in mind, you can start adapting your business to better make use of this trend in order for your business to grow. It’s important to remain ahead of the competition if you want your business to flourish. This is why I’m going to give you some tips on how to better optimize your website for voice search:

Tips for Voice Search Optimization

1. Understand the Language: People that are using voice usually are not searching for just one keyword. Instead, they are using long sentences that describe what they are looking for. If you want to make your content more relevant for voice search, then you will have to adapt and use long sentences that are likely to be in tune with what the customer is saying when searching for content that is similar to what you’re offering.

 

2. Be Conversational: In order to improve the likelihood to be found when people are voice searching for your content, you will have to keep the keyphrase at a conversational level. The person that is searching for content using voice search is also going to keep it conversational. In this way, you can increase your chances of being found.

 

3. Answer Questions: When people are using voice search to find out stuff on the internet, they are asking questions. Thus, if you are able to pinpoint the questions that are going to be asked in order for your content to be found, you will have to adapt your keyphrase accordingly. This will certainly increase your chances to share your content with the curious reader.

More chatbots

Another one of the digital marketing trends that does not seem to slow down is the adoption of chatbots. Chatbots have seen an astounding amount of limelight in the past year and are currently part of the digital marketing trends of 2020. Of course, chatbots still have a long way to develop before they can perform more complex tasks, but as with every technology that is in its beginning stage, it is going to become better with time.

 

Juniper Research has done some research on the adoption and projection of the chatbots in the future. Chatbots are really good at cutting costs for business. Not only that, but they can also increase the revenue generated for a business.

 

On top of that, a chatbot is extremely useful when it comes to answering basic questions that required a human in the past years. They definitely cut costs and time for your support team. Your support team can now focus on answering more complex questions, instead of having to sit through the most basic ones that a customer might have. This will also lead to a more satisfied customer, as the time queues that they would have to wait for an answer from the support team are drastically shortened.

Increase the amount of automation

Since today's world is incredibly fast-paced, you will have to find ways to increase your efficiency, while decreasing the workload and keep up with the digital marketing trends. Start trying to automate the tasks that are repetitive and time-consuming. Instead of having to focus on sending 100 emails, for example, use a software that will automate that for you. This will make it easier for you to invest time in other more important tasks that you have to take care of.

No-code website design

In the past years, we have seen the rise of the no-code website design software. However, in the upcoming year, their popularity is only going to rise. The reason for this is that these tools are speeding up the process and are cutting down the costs of designing and modifying a web page. In other words, these types of software will lower the barrier of entry for people and businesses wishing to design a visually appealing content for the web but lack the technical knowledge of coding.

Marketing departments will finally be able to edit a webpage that matches their creative concepts without having to involve the IT department, with the magic of WYSIWYG (What You See Is What You Get). In the near future, designing a website and building effect multi-media content for the web will become accessible to a larger pool of people. So, if you always wanted to design your own website but lacked the knowledge of how to do it, you can pick up a tool like our visual Drupal-based drag and drop page builder Glazed Builder and start building your own visually stunning website easier than ever before.

Hyper-targeted Ads

Learn to use the data that your website has gathered from your visitors. Not only that but also the data that you can gather from Google. This will make it much easier for you to find the people that are actually interested in what you have to offer. Not only will it cut the cost of your advertisements, but it will also increase the quality of the leads that are going to come to your website intrigued by your product or service. In a nutshell, start analyzing and start targeting. 

What digital marketing trends are you watching?

Did we miss any important trends or do you want to share your insights on some of the above mentioned digital marketing trends? Drop a comment and let us know!

Amazee Labs: DrupalCon Amsterdam Day 3 Recap 

Main Drupal Feed - Thu, 10/31/2019 - 10:01
After a night full of singing Karaoke with the fellow Amazees, the day started a bit slower and later than usual. I made my way down to the lobby to catch a ride to the venue. 

Bounteous.com: Introducing Migrate Source JCR

Main Drupal Feed - Wed, 10/30/2019 - 18:55
Migrate Source JCR is a Drupal module that allows you to extract AEM data, transform it, and load directly into Drupal to assist with AEM to Drupal migrations.

Drudesk: Modules to work with databases in Drupal

Main Drupal Feed - Wed, 10/30/2019 - 15:12

Working with databases can be challenging and cumbersome. Luckily, there are useful Drupal modules that make complicated tasks easy (or possible at all). Of course, the best way to achieve the desired results is to rely on Drupal development and DevOps services by Drudesk. In the meantime, we are sharing great modules for working with databases in Drupal with you.

Some challenges with databases in Drupal

While working with databases, it may be needed to:

Pages