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:
Task: Rich text rendering
Follow these steps to implement rendering of the bio field in Next.js
-
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.tsimport {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.
-
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 passbio
data from the query response to theRichTextView
component.Create new component with the following content:
src/components/views/PersonWithBio.tsximport 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; }
-
Update the mapping
Finally, we need to update the mappings to use the new query and view.
Simply replace the
getPerson
query withgetPersonWithBio
andPerson
view withPersonWithBio
. It should look something like this:src/components/_mappings.tsimport getPersonWithBio from './queries/getPersonWithBio'; import PersonWithBio from './views/PersonWithBio'; ComponentRegistry.addContentType(`${APP_NAME}:person`, { query: getPersonWithBio, view: PersonWithBio });
-
That’s it!
The resulting page for Lea Seydoux should look like this:
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.