reactjsgraphqlgatsbynetlifynetlify-cms

Add custom Netlify CMS widget to Gatsby starter Yellowcake


I am working with the Gatsby starter 'YellowCake' which is has Netlify CMS as part of it.

I am trying to add another custom widget to the starters Contact Page. I would like to add "Fax" under "Phone". I have added it to the config.yml file and added a fax number to my contact.md file and I have added it to my ContactPage.js template. But it is not showing up on the page.

I am not sure what I am missing or doing wrong. Would love any help.

Config.yml

collections: # A list of collections the CMS should be able to edit
  - name: 'pages'
    label: 'Page'
    delete: false # Prevent users from deleting documents in this collection
    editor:
      preview: true
    files:
      - file: 'content/pages/contact.md'
        label: 'Contact Page'
        name: 'contact-page'
        fields:
          - {
              label: Template,
              name: template,
              widget: hidden,
              default: ContactPage,
            }
          - { label: Slug, name: slug, widget: hidden, default: 'contact' }
          - { label: Title, name: title, widget: string }
          - {
              label: Featured Image,
              name: featuredImage,
              widget: image,
              options:
                { media_library: { config: { imageShrink: 2600x2600 } } },
            }
          - { label: Subtitle, name: subtitle, widget: markdown }
          - { label: Body, name: body, widget: markdown }
          - { label: Address, name: address, widget: text }
          - { label: Phone, name: phone, widget: string }
          - { label: Fax, name: fax, widget: string }
          - { label: Email Address, name: email, widget: string }

contact.md

template: ContactPage
slug: contact
title: Contact Page
featuredImage: https://ucarecdn.com/e22a858a-b420-47af-99f6-ed54b6860333/
subtitle: This is the contact page subtitle.
address: '404 James St, Burleigh Heads QLD 4220'
phone: 0987 123 456
fax: 333-333-3333
email: example@example.com

ContactPage.js (template)

import React from 'react'
import { MapPin, Smartphone, Mail, Printer } from 'react-feather'
import { graphql } from 'gatsby'

import PageHeader from '../components/PageHeader'
import FormSimpleAjax from '../components/FormSimpleAjax'
import Content from '../components/Content'
import GoogleMap from '../components/GoogleMap'
import Layout from '../components/Layout'
import './ContactPage.css'

// Export Template for use in CMS preview
export const ContactPageTemplate = ({
  body,
  title,
  subtitle,
  featuredImage,
  address,
  phone,
  fax,
  email,
  locations
}) => (
  <main className="Contact">
    <PageHeader
      title={title}
      subtitle={subtitle}
      backgroundImage={featuredImage}
    />
    <section className="section Contact--Section1">
      <div className="container Contact--Section1--Container">
        <div>
          <Content source={body} />
          <div className="Contact--Details">
            {address && (
              <a
                className="Contact--Details--Item"
                href={`https://www.google.com/maps/search/${encodeURI(
                  address
                )}`}
                target="_blank"
                rel="noopener noreferrer"
              >
                <MapPin /> {address}
              </a>
            )}
            {phone && (
              <a className="Contact--Details--Item" href={`tel:${phone}`}>
                <Smartphone /> {phone}
              </a>
            )}
            {fax && (
              <a className="Contact--Details--Item" href={`fax:${fax}`}>
                <Printer /> {fax}
              </a>
            )}
            {email && (
              <a className="Contact--Details--Item" href={`mailto:${email}`}>
                <Mail /> {email}
              </a>
            )}
          </div>
        </div>

        <div>
          <FormSimpleAjax name="Simple Form Ajax" />
        </div>
      </div>
    </section>

    <GoogleMap locations={locations} />
  </main>
)

const ContactPage = ({ data: { page } }) => (
  <Layout
    meta={page.frontmatter.meta || false}
    title={page.frontmatter.title || false}
  >
    <ContactPageTemplate {...page.frontmatter} body={page.html} />
  </Layout>
)

export default ContactPage

export const pageQuery = graphql`
  query ContactPage($id: String!) {
    page: markdownRemark(id: { eq: $id }) {
      ...Meta
      html
      frontmatter {
        title
        template
        subtitle
        featuredImage
        address
        phone
        email
        locations {
          mapLink
          lat
          lng
        }
      }
    }
  }
`

Solution

  • You are not fetching the fax field in your GraphQL query:

    export const pageQuery = graphql`
      query ContactPage($id: String!) {
        page: markdownRemark(id: { eq: $id }) {
          ...Meta
          html
          frontmatter {
            title
            template
            subtitle
            featuredImage
            address
            phone
            email
            fax # <-- here
            locations {
              mapLink
              lat
              lng
            }
          }
        }
      }
    `
    

    The rest of the code should work alone because of the destructure and the rendering of fax under phone in the JSX.

    "Cannot query field 'fax' on type 'MarkdownRemarkFrontmatter'"

    Among running gatsby clean and testing your query in the localhost:8000/___graphql playground. It's strange that you have a hidden field called slug (with contact value) but you are not using it. In your case I would use a page query such as:

    export const contactData = graphql`
        query getContactData {
            page: allMarkdownRemark(
                filter: { frontmatter: { slug: { eq: "contact" }}}) {
                edges {
                    node {
                     ...Meta
                     html
                     frontmatter {
                       title
                       template
                       subtitle
                       featuredImage
                       address
                       phone
                       fax
                       email
                       locations {
                          mapLink
                          lat
                          lng
                         }
                      }
                   }
                }
            }
        }
    `;
    

    Then something like:

    const ContactPage = ({ data: { page: {
          edges: [{
            node: {
              html,
              frontmatter
            }
          }]
        }}}) => (
      <Layout
        meta={frontmatter.meta || false}
        title={frontmatter.title || false}
      >
        <ContactPageTemplate {...frontmatter} body={html} />
      </Layout>
    )