Parts

Contents

Intro

Parts are highly flexible components which may be used to enrich your pages. Each part is like a content type, with an optional form that can be used to create content.

Child list component

Take a look at the Person folder. You may see something like this: child list no render

  1. Add the child-list component to your front-end:

    /src/main/resources/react4xp/components/parts/ChildList.tsx
    import {Part} from "@enonic/react-components";
    import React from "react";
    import styles from "./ChildList.module.css";
    
    
    export const ChildList = (props) => {
    
        const {names, paths, componentRegistry, ...partProps} = props;
        return (
            <Part {...partProps}>
                {names?.length > 0 && <ul>
                    {names.map((name, index) => (
                        <li className={styles.listItem} key={index}>
                            <a className={styles.listLink} href={paths[index]}><p>{name}</p></a>
                        </li>
                    ))}
                </ul>}
            </Part>
        );
    };
    /src/main/resources/react4xp/components/parts/ChildListProcessor.ts
    import type {ComponentProcessorFunction} from '@enonic-types/lib-react4xp/DataFetcher';
    import {getChildren} from '/lib/xp/content';
    import {PartComponent} from '@enonic-types/core';
    
    export const childListProcessor: ComponentProcessorFunction<'com.enonic.app.hmdb:child-list'> = (params) => {
        const component = params.component as PartComponent;
        const sortOrder: any = component.config.sorting;
    
        const result = getChildren({
            key: params.content._id,
            start: 0,
            count: 99,
            sort: sortOrder
        });
    
        return {
            names: result.hits.map((content) => content.displayName),
            paths: result.hits.map((content) => params.request.path + '/' + content._name),
        };
    };
    /src/main/resources/react4xp/components/parts/ChildList.module.css
    ul {
      list-style: none;
      padding-left: 0;
    }
    
    .listItem {
      margin-block: .25rem;
    }
    
    .listLink {
      color: #61DBFB;
      text-decoration: none;
      font-weight: 500;
    }
    
    .listLink p {
      margin-block: 0;
    }
  2. Register the component and processor:

    /src/main/resources/react4xp/componentRegistry.ts
    import {ChildList} from './components/parts/ChildList';
    
    ...
    
    export const componentRegistry = new ComponentRegistry();
    
    ...
    
    componentRegistry.addPart('com.enonic.app.hmdb:child-list', {View: ChildList});
    /src/main/resources/react4xp/dataFetcher.ts
    import {childListProcessor} from './components/parts/ChildListProcessor';
    
    ...
    
    export const dataFetcher = new DataFetcher();
    
    ...
    
    dataFetcher.addPart('com.enonic.app.hmdb:child-list', {processor: childListProcessor});
  3. Refresh the Persons page to see the result: child list render

    Try updating the CMS component by changing the sorting order, or even adding or removing items within the tree structure.

child list form

Bonus task: Heading

HMDB also contains data for one more part, Heading. Follow the steps below to start rendering the heading as well:

  1. Add the heading component to your application:

    /src/main/resources/react4xp/components/parts/Heading.tsx
    import {Part} from '@enonic/react-components';
    import React from 'react';
    
    export const Heading = (props: any) => {
    
        const {componentRegistry, ...partProps} = props;
        return <Part {...partProps}>
            <h1>{props.heading}</h1>
        </Part>
    };
    /src/main/resources/react4xp/components/parts/HeadingProcessor.ts
    import {PartComponent} from '@enonic-types/core';
    import type {ComponentProcessorFunction} from '@enonic-types/lib-react4xp/DataFetcher';
    
    export const headingProcessor: ComponentProcessorFunction<'com.enonic.app.hmdb:heading'> = (params) => {
        const component = params.component as PartComponent;
        const heading = component.config?.heading || params.content.displayName;
    
        return {
            heading: heading,
        };
    
    };

    Since we are using globalStyles.css to style the heading, we don’t need to add a CSS module for this component.

  2. Add the heading part to your component registry and data fetcher:

    /src/main/resources/react4xp/componentRegistry.ts
    import {ChildList} from './components/parts/ChildList';
    import {Heading} from './components/parts/Heading';
    
    ...
    
    export const componentRegistry = new ComponentRegistry();
    
    ...
    
    componentRegistry.addPart('com.enonic.app.hmdb:child-list', {View: ChildList});
    componentRegistry.addPart('com.enonic.app.hmdb:heading', {View: Heading});
    /src/main/resources/react4xp/dataFetcher.ts
    import {childListProcessor} from './components/parts/ChildListProcessor';
    import {headingProcessor} from './components/parts/HeadingProcessor';
    
    ...
    
    export const dataFetcher = new DataFetcher();
    
    ...
    
    dataFetcher.addPart('com.enonic.app.hmdb:child-list', {processor: childListProcessor});
    dataFetcher.addPart('com.enonic.app.hmdb:heading', {processor: headingProcessor});
  3. Now you should be able to see something like this: header

Moving on, we take page composition to the next level. Introducing layouts.


Contents

Contents

AI-powered search

Juke AI