How to create breadcrumbs with angular?

Discussão em 'Angular' iniciado por Szigmahun, Janeiro 8, 2025.

  1. Szigmahun

    Szigmahun Guest

    I’m working on a project that requires implementing breadcrumb navigation to display the datasheets the user has previously visited. For example:

    xz-search/x-datasheet/x-datasheet-contracts/contract-item/supplier

    The current implementation uses a manual approach, where a from value is passed through query parameters (e.g., ...plan/datasheet/123/data?from=order-datasheet&order=432&customOrderId=123123). In each component that includes a breadcrumb, a switch statement manually handles the various possible routes leading to the component.

    export interface Breadcrumb {
    label?: string
    navList: BreadcrumbNav[]
    }

    export interface BreadcrumbNav {
    label: string
    description?: string
    url: string[]
    urlExtras?: NavigationExtras
    }
    const from = queryParams['from']
    private createBreadcrumb(from?: string, planId?: string, customPlanId?: string) {
    let claimBaseNavItem: BreadcrumbNav[]
    switch (from) {
    case 'search':
    claimBaseNavItem = [
    {
    label: `Search`,
    url: ['/', this.entityType, 'plan', 'search']
    }
    ]
    break....


    However, as the project has grown with more modules and navigation links, this approach has become unmanageable. Additionally, users need consistent breadcrumb navigation even when copying or sharing URLs.

    Constraints:


    • Libraries cannot be used.


    • Breadcrumbs may contain submenus or independent URLs.


    • Breadcrumb IDs differ from the IDs in the URL, and components can only access these IDs through the URL.

    Challenges:


    1. Preventing circular references: For instance, if a datasheet links to related contracts, contracts link to suppliers, and suppliers link back to the same datasheet, the breadcrumb should truncate the loop after the datasheet.


    2. Query parameters: I tested a solution using bc query parameters containing a hashed, stringified array of {label: string} objects.
      Testing new solution:

      public createBreadcrumbQueryParams(actualLabel: string) {
      const currentBreadcrumbData = this.route.snapshot.queryParams['bc']
      ? JSON.parse(atob(this.route.snapshot.queryParams['bc']))
      : null

      if (currentBreadcrumbData) {
      //find if current page is already in breadcrumb
      const index = currentBreadcrumbData.findIndex(
      (item) => item.label === formatStringToBase64Compatible(actualLabel)
      )
      const urlsToProcess =
      index !== -1 ? currentBreadcrumbData.slice(0, index) : currentBreadcrumbData

      urlsToProcess.push({
      url: this.router.url.split('?bc=')[0],
      urlExtras: {
      queryParams: this.route.snapshot.queryParams['bc']
      },
      label: formatStringToBase64Compatible(actualLabel)
      })

      const bc = btoa(JSON.stringify(urlsToProcess))
      return bc
      }
      return null
      }


      Example for created url: claim/datasheet/123/data?bc=W3sidXJsIjoiL29yZ2FuaXphdGlvbi9jbGFpbS90YX...

      that contains an object like this:

      breadcrumbData[
      {
      "url": "/claim/task-organization/preparation",
      "label": "Search"
      },
      {
      "url": "/claim/datasheet/321/plan-part",
      "urlExtras": {
      "queryParams": "W3sidXJsIjoiL29yZ2FuaXphd..."
      },
      "label": "Claim - 123"
      }
      ]


      However, this can result in excessively long query parameters if many pages were visited 2-3000 characters long which is not good i suppose...

    What approach can I use to pass on or store the previous URLs while addressing these constraints?

    Continue reading...

Compartilhe esta Página