Adding Dynamic Routes to Umbraco 14 Sections

Yari Mariën - Oct 7 - - Dev Community

Introduction

In this post, I'll be building on concepts from my previous post, where we covered creating custom sections in Umbraco 14.

We'll focus on the following topics:

  • Adding routing to our section view
  • Creating a root page for our custom section
  • Displaying a detailed view when a tree item is clicked

Setting Up a Generic Section View

Adding a page behind a tree item is essential for adding functionality to our custom section. In this example, I'll demonstrate how to add a page to tree items of the type "Form." Upon clicking, a view containing a form builder will be displayed. For this, we’ll use a SectionView along with Umbraco's Router functionality.

Section View Manifest

We’ll use the same section view as in the previous example, but with updates. Specifically, we’ll add conditions so it's only rendered within our custom section and update the pathname to "forms", which will be reused across all routes.

manifest.ts:

const sectionViews: Array<ManifestSectionView> = [
    {
        type: "sectionView",
        alias: FORMX_CREATEFORM_SECTION_VIEW_ALIAS,
        name: "Create Form Section View",
        element: () => import('./form-section.ts'),
        meta: {
            label: "Create Form",
            pathname: "forms",
            icon: "icon-add"
        },
        conditions: [
            {
                alias: 'Umb.Condition.SectionAlias',
                match: FORMX_SECTION_ALIAS,
            }
        ]
    }
];

export const sectionViewsManifest = [...sectionViews];
Enter fullscreen mode Exit fullscreen mode

Adding Routing

We'll use the form-section.ts component as a wrapper for all possible routes in our custom section. First, define an array of possible routes using UmbRoute. Each route will have a component and setup property, which we can use to load components and pass relevant properties.

In this example, I’ve added routes for a section root, create form, and edit form.

form-section.ts:

const element = "formx-section";
@customElement(element)
export class FormXSection extends UmbLitElement {

    #routes: UmbRoute[] = [
        {
                //Section & Tree root
            path: 'root',
            component: () => import('./form-section-root'),
        },
        {
                //Create form route
            path: 'create/:parentId',
            component: () => import('./form-section-create-form')
        },
        {
                //Edit form route
            path: 'edit/:id',
            component: () => import('./form-section-create-form')
        },
        {
                //Catch empty routes and redirect to root
            path: '',
            redirectTo: 'root',
        },
        {
                //Catch other routes and return to not Found
            path: `**`,
            component: async () => (await import('@umbraco-cms/backoffice/router')).UmbRouteNotFoundElement,
        },
    ];


//...
Enter fullscreen mode Exit fullscreen mode

Next, pass the routes to an umb-router-slot to enable navigation.

form-section.ts:

render() {
    return html`
    <umb-router-slot id="router-slot" .routes=${this.#routes}></umb-router-slot>
`
}
Enter fullscreen mode Exit fullscreen mode

Root Route

To set up the root route, we can use a simple Lit Element to display some basic information.

const element = "formx-section-root";

@customElement(element)
export class FormxSectionRoot extends UmbLitElement{
    protected render = () => {
        return html`<div>Form Section Root... Some information here.</div>`;
    }
}

export default FormxSectionRoot;

declare global {
    interface HTMLElementTagNameMap {
        [element]: FormxSectionRoot;
    }
}

Enter fullscreen mode Exit fullscreen mode

When you navigate to the section, the root element will be displayed.

Root route example

Setting Up Create & Edit Route Components

In this example, I’m using the same component for both the create and edit routes, enabling the form builder to be used for both scenarios.

The component has two key properties: editMode and idProp. The idProp is used for the parentId or formId, while editMode determines if the form is in create or edit mode. If editMode is true, idProp will contain the formId; otherwise, it will hold the parentId.

form-section-create-form.ts:

@customElement(element)
export class FormxSectionCreateForm extends UmbLitElement {

    //Id of the form or parent
    @property({ type: String })
    public idProp!: string;

    //If edit mode is enabled the id is the id of the form
    //If edit mode is disabled the id is the id of the parent
    @property({ type: Boolean })
    public editMode: boolean = false;

    @state()
    items: CreateFormField[] = [];

      private _parentId: number = -1; 
    private _id: number = 0;
    private _title: string = "Create Form";

    constructor() {
        super();
    }

//....
Enter fullscreen mode Exit fullscreen mode

We can set the values of these properties using the setup property of the UmbRoute.

form-section.ts:

const element = "formx-section";
@customElement(element)
export class FormXSection extends UmbLitElement {

    #routes: UmbRoute[] = [
        {
                //Section & Tree root
            path: 'root',
            component: () => import('./form-section-root'),
        },
        {
                //Create form route
            path: 'create/:parentId',
            component: () => import('./form-section-create-form'),
            setup: (component, info) => {
                const element = component as FormxSectionCreateForm;
                element.idProp = info.match.params.parentId;
                element.editMode = false;
            }
        },
        {
                //Edit form route
            path: 'edit/:id',
            component: () => import('./form-section-create-form'),
            setup: (component, info) => {
                const element = component as FormxSectionCreateForm;
                element.idProp = info.match.params.id;
                element.editMode = true;
            }
        },
        {
                //Catch empty routes and redirect to root
            path: '',
            redirectTo: 'root',
        },
        {
                //Catch other routes and return to not Found
            path: `**`,
            component: async () => (await import('@umbraco-cms/backoffice/router')).UmbRouteNotFoundElement,
        },
    ];


//...
Enter fullscreen mode Exit fullscreen mode

To capture the updated values, use the firstUpdated method.

form-section-create-form.ts:

  firstUpdated(): void {

      if(this.editMode){
          this._id = parseInt(this.idProp);
          this._title = "Edit Form";
      }
      else{
          this._parentId = parseInt(this.idProp);
          this._title = "Create Form";
      }

            //... Use values
  }
Enter fullscreen mode Exit fullscreen mode

Adding Routing to the Tree

To add routing to the tree items, use the href attribute to navigate to the appropriate route.

//Type 0 === form
<uui-menu-item  href=${element.type == 0 ? `section/FormX/view/forms/edit/${element.id}` : ''}>
</uui-menu-item>
Enter fullscreen mode Exit fullscreen mode

When a tree item is clicked, the edit component will be displayed.

Edit route example

. . .
Terabox Video Player