Rich Text

Contents

In this chapter you’ll learn how to render rich text content.

Intro

Enonic boasts a rich text input type. Unlike basic text fields, rich text may contain more complex concepts such as tables, images, links and custom components. Each of these will typically need to be processed during rendering in order to provide a contextually correct URL, ideal image sizes etc.

Sample content

Luckily, the sample data set contains everyting we need to get going. The Bio field for persons is rich text, and some of the content is even populated with relevant content, like you see below:

rich text bio
Figure 1. Rich text bio field for Lea Seydoux

Task: Rich text rendering

Follow these steps to implement rendering of the bio field in Next.js

  1. Update the Person query

    To properly render Rich text, we need access to additional metadata such as links, images within it.

    To simplify things, Next.XP provides a richTextQuery helper function that generates the query for us. Also, this way we don’t have to repeat the query for every rich text field.

    Add a new query file to your project with the following content:

    src/components/queries/getPersonWithBio.ts
    import {APP_NAME_UNDERSCORED, richTextQuery} from '@enonic/nextjs-adapter';
    
    const getPerson = () => `
    query($path:ID!){
      guillotine {
        get(key:$path) {
          displayName
          ... on ${APP_NAME_UNDERSCORED}_Person {
            data {
              ${richTextQuery('bio')}
              dateofbirth
              photos {
               ... on media_Image {
                  imageUrl: imageUrl(type: absolute, scale: "width(500)")
                  attachments {
                    name
                  }
                }
              }
            }
          }
          parent {
            _path(type: siteRelative)
          }
        }
      }
    }`;
    
    export default getPerson;
    Since we use ${richTextQuery('bio')}` now, that is dependant on registered macros, getPerson query must now be a function! This guarantees that it is executed when querying for data, and all the macros are already registered.

    For further insight, visit the rich text chapter in the Developer 101 tutorial, or have a look at the tutorial covering our standard react components.

  2. The RichTextView component

    Now that we got the data, we need to use RichTextView component that knows how to render it. All we need to do is pass bio data from the query response to the RichTextView component.

    Create new component with the following content:

    src/components/views/PersonWithBio.tsx
    import React from 'react'
    import {FetchContentResult, getUrl, I18n} from '@enonic/nextjs-adapter';
    import Link from 'next/link';
    import RichTextView from '@enonic/nextjs-adapter/views/RichTextView';
    import styles from './PersonWithBio.module.css';
    
    const Person = (props: FetchContentResult) => {
        const {displayName, data, parent} = props.data?.get as any;
        const {bio, photos} = data;
        const meta = props.meta;
    
        return (
            <>
                <div className={styles.person}>
                    <h2>{displayName}</h2>
                    <RichTextView className={styles.bio} data={bio} meta={meta}></RichTextView>
                    {
                        photos.length && <h4 className={styles.photosheader}>Photos</h4>
                    }
                    <div className={styles.photos}>
                        {
                            photos.map((photo: any, i: number) => (
                                <img key={i}
                                     src={getUrl(photo.imageUrl, meta)}
                                     title={getTitle(photo, displayName)}
                                     alt={getTitle(photo, displayName)}
                                     width="500"
                                />
                            ))
                        }
                    </div>
                </div>
                <p><Link href={getUrl(`/${parent._path}`, meta)}>{I18n.localize('back')}</Link></p>
            </>
        )
    }
    
    export default Person;
    
    function getTitle(photo: any, displayName: string) {
        return (photo.attachments || [])[0].name || displayName;
    }
  3. Update the mapping

    Finally, we need to update the mappings to use the new query and view.

    Simply replace the getPerson query with getPersonWithBio and Person view with PersonWithBio. It should look something like this:

    src/components/_mappings.ts
    import getPersonWithBio from './queries/getPersonWithBio';
    import PersonWithBio from './views/PersonWithBio';
    
    ComponentRegistry.addContentType(`${APP_NAME}:person`, {
        query: getPersonWithBio,
        view: PersonWithBio
    });
  4. That’s it!

    The resulting page for Lea Seydoux should look like this:

    rich text no macro
    Figure 2. Person content rendered with rich text

As you can see from the above screenshot, there is a missing component. The next chapter addresses this by looking into Macros.


Contents

Contents

AI-powered search

Juke AI