Planet Drupal

Subscribe to Planet Drupal feed
Drupal.org - aggregated feeds in category Planet Drupal
Updated: 22 hours 56 min ago

PreviousNext: Using Drupal's Entity Definition Update Manager to add bundle support to an existing content entity

4 November 2019 - 7:11pm

On a client project we were using a custom Drupal content entity to model some lightweight reusable content.

The content entity was originally single use and did not support bundles (e.g. node entities have node-type bundles).

As the project evolved, we needed to add bundle support for the custom entity-type, despite it already being in production use.

Read on to find out how we achieved this.

by Lee Rowlands / 5 November 2019

In this example, lets call the content entity a 'set' and the bundles a 'set type'.

Create the bundle configuration entity

As we wanted this content entity to support adding new bundles via the UI, a configuration entity makes sense to allow site-builders to create the various bundles as required, so we created a new configuration entity called 'set type' as per the examples, although we used a route provider instead of a routing file. We made sure to add the bundle_of annotation to the config entity.

bundle_of = "set",Updating the content entity's annotation and fields

Once this was done, the next step was to update the content entity's annotation. We added the 'bundle' key and the 'bundle_entity_type' annotation

bundle_entity_type = "set_type", * entity_keys = { * "id" = "id", * "label" = "name", * "uuid" = "uuid", * "uid" = "user_id", * "bundle" = "type", * "langcode" = "langcode", * },

We didn't need to add a new field for our baseFieldDefinition to our content entity because we just deferred to the parent implementation. But we made sure to match up the description, label etc as desired - and that we called setInitialValue. As we're planning to add a new column to the entity's tables in the database, we need to populate the type column for existing records. Now with entities that don't support bundles, Drupal defaults to the entity ID for the bundle. e.g. for the 'user' entity, the bundle is always 'user' because User entities don't support bundles. So we knew our existing 'set' entities would have to have a bundle of 'set' too. But our new ones could have whatever we liked. So this is why our field definition for 'type' had to have look like so

$fields['type']->setInitialValue('set')Update hooks to get everything in place

Since Drupal 8.7, support for automatic entity updates has been removed, so whilst adding the field, entity keys and updating the annotation works for a new install (hint, there won't be one) it doesn't help our existing production and QA sites - so we need an update hook to bring our existing entity-type and field definitions into sync with the code versions, which also takes care of the required database table changes.

So the steps we need to do here are:

  1. install the config entity type
  2. create a new instance of it for the existing entities
  3. add the new field definition for the type field to the content entity
  4. update the content entity definition
Installing the config entity type

The docs for installing a new entity type make it clear what we need to do. Our code ended up something like this:

/** * Adds the set type. */ function your_module_update_8001() { \Drupal::entityDefinitionUpdateManager() ->installEntityType(new ConfigEntityType([ 'id' => 'set_type', 'label' => new TranslatableMarkup('Set type'), 'label_collection' => new TranslatableMarkup('Set types'), 'label_singular' => new TranslatableMarkup('set type'), 'label_plural' => new TranslatableMarkup('set types'), 'label_count' => [ 'singular' => '@count set type', 'plural' => '@count set types', ], 'handlers' => [ 'list_builder' => 'Drupal\your_module\SetTypeListBuilder', 'form' => [ 'default' => 'Drupal\your_module\Form\SetTypeForm', 'delete' => 'Drupal\Core\Entity\EntityDeleteForm', ], 'route_provider' => [ 'html' => 'Drupal\Core\Entity\Routing\AdminHtmlRouteProvider', ], ], 'admin_permission' => 'administer set type entities', 'entity_keys' => [ 'id' => 'id', 'label' => 'name', ], 'links' => [ 'add-form' => '/admin/structure/sets/add', 'delete-form' => '/admin/structure/sets/manage/{pane_set_type}/delete', 'reset-form' => '/admin/structure/sets/manage/{pane_set_type}/reset', 'overview-form' => '/admin/structure/sets/manage/{pane_set_type}/overview', 'edit-form' => '/admin/structure/sets/manage/{pane_set_type}', 'collection' => '/admin/structure/sets', ], 'config_export' => [ 'name', 'id', 'description', ], ])); }Creating the first bundle

In our first update hook we installed the config entity, now we need to make one for the existing entities, because bundle-less entities use the entity type ID as the bundle, we make sure our new type has the same ID as the entity-type.

/** * Adds a new config entity for the default set type. */ function your_module_update_8002() { $type = SetType::create([ 'id' => 'set', 'name' => 'Set', 'description' => 'Provides set panes', ]); $type->save(); }Adding the new field definition and updating the entity definition

The documentation for adding a new field definition is again very useful here, so we follow along to install our new field definition. And similarly the documentation for updating an entity type here, so our final update hook looks like this:

/** * Updates defintion for set entity. */ function your_module_update_8003() { $updates = \Drupal::entityDefinitionUpdateManager(); $definition = BaseFieldDefinition::create('entity_reference') ->setLabel('Set type') ->setSetting('target_type', 'set_type') ->setRequired(TRUE) ->setReadOnly(TRUE) ->setInitialValue('set') ->setDefaultValue('set'); $updates->installFieldStorageDefinition('type', 'your_module', 'your_module', $definition); $type = $updates->getEntityType('your_module'); $keys = $type->getKeys(); $keys['bundle'] = 'type'; $type->set('entity_keys', $keys); $type->set('bundle_entity_type', 'pane_set_type'); $updates->updateEntityType($type); }

And that's it we're done.

Wrapping up

Kudos to those who created the documentation for this, as well as my colleagues Sam Becker, Jibran Ijaz and Daniel Phin who helped me along the way. Hopefully, you find this post useful if you're ever in the same boat.

Tagged Content entities, Drupal 8, Entity Definition Update Manager, Bundles
Categories: Drupal

Hook 42: Drupal Core Initiative Meetings Recap - October 28 - November 01, 2019

4 November 2019 - 10:30am
Drupal Core Initiative Meetings Recap - October 28 - November 01, 2019 Lindsey Gemmill Mon, 11/04/2019 - 18:30
Categories: Drupal

Acro Media: Making Drupal Code Standards Work for You With PhpStorm & phpcs/phpcbf

4 November 2019 - 7:45am
A proactive approach for cleaner Drupal coding


So you are stuck in the cruft, struggling to create some semblance of sanity within a sea of code-rot. Code standards sound like a great idea for your project, but perhaps automated enforcement tools look like more of a pain than they're worth. This post is intended for Drupal developers using PhpStorm who need fast, flexible, standards enforcement tools.

Maintaining a stringent standard for your codebase is a battle. On one hand, your code is cleaner, more unified, and easier to maintain. On the other hand, these little formatting rules cause frustration and time loss - especially if a tiny slip causes you to waste a full pipeline cycle just to pass an automated standards check. As they say, the best defence is a strong offence, and the tools proposed here will help you find and fix standards violations before they reach a pipeline.

Drupal recommends a tool called PHP Code Sniffer, aka phpcs, to scan your files for Drupal Code Standards violations. Thankfully, it also comes with a companion tool called PHP Code Beautifier and Fixer, aka phpcbf, which fixes the small, tedious violations for you.

The goal of this post is to get phpcs and phpcbf under your fingertips and into your habits. Only once you have hotkeys set-up to run these tools while coding will they become useful — instead of just annoying.

The steps are as follows:

  1. Install and set-up phpcs
  2. Create a custom combination of rulesets
  3. Integrate with PhpStorm for hotkeys and syntax highlighting
1. Install and set-up phpcs

It may seem straightforward to install phpcs globally via Composer or apt, or to simply require it in your current composer project. However, a global install is not easy to customize and share. Instead, I recommend using a standalone repo that is specifically for your code standards tools. When your standards stand alone, they are easier to edit, share with teammates, and transfer to new work environments.

Here’s a simple repo to get you started:
https://github.com/nilswloewen/drupal_code_standards

  1. If you currently have phpcs or phpcbf installed globally, uninstall them before proceeding.

  2. Quick install with example repo:

    git clone git@github.com:nilswloewen/drupal_code_standards.git
    cd drupal_code_standards
    composer install
  3. Once composer has installed phpcs for you, add it to your global path with:

    export PATH=$PATH:~/PATH/TO/drupal_code_standards/vendor/bin
    NOTE: Adjust accordingly for your shell and OS of choice.

  4. Next, you must tell phpcs which rulesets you have installed use.

    The optional tool phpcodesniffer-composer-installer will automatically detect rulesets in your composer package and set your phpcs & phpcbf installed_paths for you. This is part of the example repo and the next step should have been done for you during "composer install".

    However, to set installed paths to rulesets manually run:

    phpcs --config-set installed_paths vendor/drupal/coder/coder_sniffer,vendor/phpcompatibility/php-compatibility/PHPCompatibility

    Then confirm that phpcs knows about the rulesets within the installed paths with:

    phpcs -i

    You should see this list that confirms your rulesets:

    The installed coding standards are ... PHPCompatibility, Drupal and DrupalPractice

    You may need to set installed paths for phpcbf as well using the same process.

2. Create a custom combination of rulesets

Out of the box, phpcs can only run one standard at a time. This is a problem when working with Drupal because we have 2 standards to follow. For this post I have added a third standard, PHPCompatibility, which is helpful when upgrading php versions on legacy projects.

  1. To combine standards we first create a custom ruleset that references multiple rulesets. Note that this is already included in the example repo as phpcs-custom-standards.xml.

    <?xml version="1.0"?>
    <ruleset name="Custom code standards">
    <rule ref="Drupal"/>
    <rule ref="DrupalPractice"/>
    <rule ref="PHPCompatibility"/>
    </ruleset>
  2. Then set this standard as your default. Use an absolute path to ensure your standard will be found no matter what context phpcs is called from.

    phpcs --config-set default_standard ~/PATH/TO/drupal_code_standards/phpcs-custom-standard.xml See the example standard for a few other helpful settings.
3. Integrate with PhpStorm for hotkeys and syntax highlighting

There are two levels of integration with PhpStorm: Passive and Active.

Passive

Passive code analysis with PhpStorm Inspections will give you syntax highlighting and hover-over explanations of the file you are currently working on.

This is quite helpful when dealing with one file at a time, but when you need to get an entire directory to pass standards, you need a way to hunt for violations.

Active

Active analysis when you use phpcs to scan many files at once. You can do this through the terminal with a command like:

phpcs ~/module # Scans all applicable files in dir.
phpcs ~/module/example.php # Scans only a specific file.

However, it’s a pain to open a terminal window, navigate to the file you are working on, and then type a command. You’ll probably forget or neglect to check your work because of these extra steps involved. A better way to run phpcs is to set-up hotkeys within PhpStorm to scan your files instantly.

Configure PhpStorm inspections
  1. Register phpcs and phpcbf as PHP Quality Tools.

    Settings | Languages and Frameworks | PHP | Quality Tools | Code Sniffer



  2. Enable the inspection.

    Settings | Editor | Inspection | PHP | Quality Tools

  • Set the extension list to match what Drupal standard sets: source

    php,module,inc,install,test,profile,theme,css,info,txt,md,yml
  • DO NOT set the "Installed standard paths", as this overrides what you have previously set in the command line.
  • The refresh list button on "Coding Standard" should mimic what "phpcs -i" shows. Choose "Custom" Coding Standard and then click the ellipses to choose the path to your custom standards file (i.e. phpcs-custom-standards.xml).
  • Click OK and your inspections should be working!
Configure hotkeys
  1. Register phpcs and phpcbf as external tools.

    Settings | Tools | External Tools

    The "$FilePath" argument runs the tool against the file you are currently working on, or against a selected folder when in project view.

  2. Double check that this step works by running the tool from the main menu.

    Tools | External Tools | phpcs

  3. This is the special sauce. Configure a keyboard shortcut for your new tools.

    Settings | Keymap | External Tools

  4. Right click on the external tool you just registered and add a keyboard shortcut. "Ctrl+Alt+Shift+Comma" was simply a combination that was not used anywhere else in my setup.

Bringing it all together

Now you can actively use phpcs and phpcbf while you code! I frequently use the phpcbf hotkey while writing new code to do the tedious stuff for me, such as creating doc blocks and pushing whitespace around. Here's an example:

With phpcs and phpcbf now under your fingertips you are set to be much more assertive in your application of code standards!

Taking it to the next level

If you are using Gitlab for CI/CD, which I hope you are, another great strategy for enforcing standards is to create a pre-deployment job that scans your custom code for violations. This will keep your team (and you) in check by stopping standards violations from being auto-deployed.

After a few super annoying pipeline failures for minor syntax errors, you will want this next level of enforcement — git pre-commit hooks. I highly recommend using grumphp to manage this for you.

Best of luck keeping your code readable and up to snuff!

End-to-end Drupal services

As a full service Drupal agency, Acro Media has significant expertise in digital commerce architecture, ecommerce design, customer experience, software development and hosting architecture. If you’re looking for a Drupal agency dedicated to code and project quality, check us out. We would love the opportunity to talk.

Categories: Drupal

TomThorp.me Blog: Mismatched Entity Error

4 November 2019 - 5:06am
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.
Categories: Drupal

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

4 November 2019 - 4:24am

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

Categories: Drupal

Web Wash: Getting Started with React in Drupal 8

4 November 2019 - 4:00am

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.

Categories: Drupal

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

3 November 2019 - 10:40am
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
Categories: Drupal

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

1 November 2019 - 10:24am

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.

Categories: Drupal

Srijan Technologies: Setup React App From Square One Without Using Create-React-App

1 November 2019 - 5:47am

The breakthrough in technology has brought a whole new range of tool suite for developers to make the software development process more efficient. React App is among one of them! A prominent tool recommended by the React community to create single-page applications (SPAs) and also get familiar with React.

Categories: Drupal

Amazee Labs: DrupalCon Amsterdam Day 4 Recap

1 November 2019 - 2:23am
After three days of some informative and inspiring talks, it was time for contribution day, so everyone got their editors out, put on their documentation hats, and got those issue queues down!
Categories: Drupal

Innoraft Drupal Blogs: Tips to Secure your Drupal Website with Ease: Basic Security checklist

31 October 2019 - 11:49pm
Tips to Secure your Drupal Website with Ease: Basic Security checklist

If someone were to break in your room, they would probably learn less about you than if they hacked you on the internet. Our efforts towards security have to be as intensive online, as they are offline.  
An extremely popular Content Management System, Drupal is on top of the list for many. 
Very importantly, Drupal has a dedicated team to make sure that the Drupal core is largely free of loopholes or vulnerabilities that may compromise website security. 

Drupal powers more than 7,00,000 sites across the internet, which increases the chance of a specific site owner being vulnerable to cyber attacks. 
Although all third-party modules are heavily vetted, a little extra security is always a good idea.

Srijeeta Ghosh Fri, 11/01/2019 - 12:19 Drupal Secure Security Drupal Planet
Categories: Drupal

Promet Source: Test blog Lorem ipsum dolor sit amet, consectetur adipi

31 October 2019 - 3:06pm
Testing Blog! Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.  
Categories: Drupal

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

31 October 2019 - 8:09am
We are happy to announce another great advancement in the Drupal user-friendliness field — the new core Help Topics module.
Categories: Drupal

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

31 October 2019 - 7:01am
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!

Categories: Drupal

Amazee Labs: DrupalCon Amsterdam Day 3 Recap 

31 October 2019 - 3:01am
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. 
Categories: Drupal

Drupalize.Me: Automated Enforcement of our Style Guide

30 October 2019 - 4:31pm
Categories: Drupal

Bounteous.com: Introducing Migrate Source JCR

30 October 2019 - 11:55am
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.
Categories: Drupal

Drudesk: Modules to work with databases in Drupal

30 October 2019 - 8:12am

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:

Categories: Drupal

Pages