Add Hyperlink in Wijmo for a particular column using Cell Maker, dynamic text

Posted by: ratnesh on 15 April 2025, 5:49 am EST

    • Post Options:
    • Link

    Posted 15 April 2025, 5:49 am EST

    Hey, I am trying to Create dynamic column for a columns rows to have a hyperLink,

    so, currently i use the wijmo in my application in library side and in application side we just pass the configurations.

    so, what i am trying here is : this.summaryGridConfig = {

    autoGenerateColumns: false,

    showMarquee: true,

    selectionMode: wjcGrid.SelectionMode.MultiRange,

    alternatingRowStep: 1,

    headersVisibility: wjcGrid.HeadersVisibility.Column,

    columns: [

    …updSrcSummaryColumns(),

    {

    binding: ‘error’,

    header: ‘Errors’,

    width: 70,

    isReadOnly: true,

    cellTemplate: CellMaker.makeLink({

    // Configure the text and click behavior of the link

    text: (ctx: wjcGrid.ICellTemplateContext) => {

    const item = ctx.item as IZPublishSummaryData;

              // Check if the cell should display a link
              const shouldShow = item?.status_desc?.toUpperCase() === 'FAILED' && item?.errors?.length > 0;
    
              if (!shouldShow) {
                return ''; // Return an empty string for empty cells
              }
    
              return 'Click Here'; // Display "Click Here" when conditions are met
            },
            click: (e: MouseEvent, ctx: wjcGrid.ICellTemplateContext) => {
              const rowData: IZPublishSummaryData = ctx.item as IZPublishSummaryData;
    
              // Check if the row has valid errors to download
              if (rowData?.status_desc?.toUpperCase() === 'FAILED' && rowData?.errors?.length) {
                this.downloadErrorJson(rowData, `error_${rowData.transaction_log_details_id}`);
              }
            },
            attributes: {
              class: 'text-blue-600 underline' // Add custom styles to the link
            }
          })
          // CellMaker.makeLink({
          //   text: (item) => (item.errors?.length > 1 ? `View Errors` : ''),
          //   click: (e: MouseEvent, ctx: wjcGrid.ICellTemplateContext) => {
          //     const rowData: IZPublishSummaryData = ctx.item as IZPublishSummaryData;
          //     if (rowData?.status_desc?.toUpperCase() === 'FAILED' && rowData?.errors?.length) {
          //       this.downloadErrorJson(rowData, `error_${rowData.transaction_log_details_id}`);
          //     }
          //   },
          //   attributes: {
          //     class: 'text-blue-600 underline'
          //   }
          // })
        }
      ],
      allowMerging: wjcGrid.AllowMerging.Cells,
      itemsSourceChanged: (s: wjcGrid.FlexGrid) => {
        setTimeout(() => {
          const row: wjcGrid.Row | undefined = s.columnHeaders.rows[0];
          if (row) row.wordWrap = true;
          // autosize first header row
          s.autoSizeRow(0, true);
        });
      },
      formatItem: (s: wjcGrid.FlexGrid, e: wjcGrid.FormatItemEventArgs) => {
        if (e.panel.cellType != wjcGrid.CellType.ColumnHeader) {
          if (e.panel.columns[e.col]?.binding == 'status_desc') {
            if (s.rows[e.row]?.dataItem['status_desc'] == 'Success') wijmo.addClass(e.cell, 'text-success');
            else {
              wijmo.addClass(e.cell, 'text-danger');
            }
          }
          const col: wjcGrid.Column | undefined = s.columns[e.col];
          const row: wjcGrid.Row | undefined = s.rows[e.row];
          const item: IZPublishSummaryData | undefined = row?.dataItem as IZPublishSummaryData;
          if (col) {
            if (col.binding == 'message') {
              if (row && item) {
                const tt: wijmo.Tooltip = new wijmo.Tooltip({ cssClass: 'wijmoCustomTooltip' });
                tt.setTooltip(e.cell, item.message);
              }
            } else if (col.binding == 'reference_id') {
              if (row) {
                const tt: wijmo.Tooltip = new wijmo.Tooltip({ cssClass: 'wijmoCustomTooltip' });
                tt.setTooltip(e.cell, item.reference_id);
              }
            } else if (col.binding === 'error' && item.status_desc?.toUpperCase() === 'FAILED') {
              wijmo.addClass(e.cell, 'text-blue-600 underline');
              // const anchor: HTMLAnchorElement = document.createElement('a');
              // anchor.textContent = 'Click Here';
              // anchor.href = 'javascript:void(0)';
              // anchor.style.color = '#1a73e8';
              // anchor.addEventListener('click', () => {
              //   this.downloadErrorJson(item, `error_${item.transaction_log_details_id}`);
              // });
    
              // e.cell.innerHTML = '';
              // e.cell.appendChild(anchor);
            }
            //   const anchor: HTMLAnchorElement = document.createElement('a');
            //   anchor.href = 'javascript:void(0)';
            //   anchor.textContent = 'Click Here';
            //   anchor.className = 'text-blue-600 underline';
            //   anchor.onclick = () => {
            //     const newWindow: Window | null = window.open();
            //     if (newWindow) {
            //       newWindow.document.write('<pre>' + JSON.stringify(item.errors, null, 2) + '</pre>');
            //       newWindow.document.title = `Error Details - ${item.transaction_log_details_id}`;
            //     }
            //   };
            //   e.cell.innerHTML = '';
            //   e.cell.appendChild(anchor);
            // }
          }
        }
      }
    };
    

    downloadErrorJson(errorData: IZPublishSummaryData, fileName: string): void {

    const blob: Blob = new Blob([JSON.stringify(errorData, null, 2)], { type: ‘application/json’ });

    const url: string = window.URL.createObjectURL(blob);

    const a: HTMLAnchorElement = document.createElement(‘a’);

    a.href = url;

    a.download =

    ${fileName}.json
    ;

    a.click();

    window.URL.revokeObjectURL(url);

    }

    export const updSrcSummaryColumns: () => IZWijmoColumnList = (): IZWijmoColumnList => {

    return [

    {

    binding: ‘transaction_log_details_id’,

    header: ‘Transaction Log ID’,

    isReadOnly: true,

    isRequired: false,

    width: 70

    },

    {

    binding: ‘day’,

    header: ‘DOW’,

    isReadOnly: true,

    isRequired: false,

    width: 80

    },

    {

    binding: ‘route_no’,

    header: ‘Route #’,

    isReadOnly: true,

    isRequired: false,

    width: 75

    },

    {

    binding: ‘status_desc’,

    header: ‘Status’,

    isReadOnly: true,

    isRequired: false,

    width: 55

    },

    {

    binding: ‘message’,

    header: ‘Message’,

    isReadOnly: true,

    isRequired: false,

    width: ‘*’

    },

    {

    binding: ‘reference_id’,

    header: ‘Reference ID’,

    isReadOnly: true,

    isRequired: false,

    width: 90

    }

    ];

    };

    also see this : <zx-wj-grid

    class=“container-data-table w-full”

    gridId=“updSrcgridId_{{ id }}”

    [gridOptions]=“summaryGridConfig”

    [gridData]=“summaryData”

    [gridBtnList]=“gridBtnListSumm”

    [exportFileName]=“exportFileName”

    [exportValues]=“exportValues1”

    (btnClickEvent)=“clickSummEvent($event)”

    [showNoDataAvailable]=“true”

    [headerSize]=“35”

    [componentMaxHeight]=“400”

    >



    so,

    what i want is text to be dynamic based on data source provided to it, like if errors have length then text should be there else it should be empty box,

    i tried this as well: cellTemplate: (ctx: wjcGrid.ICellTemplateContext) => {

    const item = ctx.item as IZPublishSummaryData;

    // Check if the cell should display a link

    const shouldShow = item?.status_desc?.toUpperCase() === ‘FAILED’ && item?.errors?.length > 0;

    if (!shouldShow) {

    return ’ '; // Return an empty cell for non-failed statuses or no errors

    }

    // Use CellMaker to generate a clickable link dynamically

    return CellMaker.makeLink({

    text: ‘Click Here’,

    click: (e: MouseEvent) => {

    this.downloadErrorJson(item,

    error_${item.transaction_log_details_id}
    );

    },

    attributes: {

    class: ‘text-blue-600 underline’ // Add custom styles to the link

    }

    })(ctx);

    }

    but doesn’t work.

    please tell me how i can do that

  • Posted 16 April 2025, 2:08 am EST

    Hi Ratnesh,

    For now, the ‘text’ property of the CellMaker class only accepts a string, we can not pass a function to there, However, you can refer to the following code snippet for setting dynamic text links in the template -

    cellTemplate: (ctx, cell) => {
              const item = ctx.item as any;
              // Check if the cell should display a link
              const shouldShow = item?.status_desc?.toUpperCase() === 'FAILED' && item?.errors?.length > 0;
              if (!shouldShow) {
                return ''; // Return an empty string for empty cells
              }
    
              // Display "Click Here" when conditions are met
              return CellMaker.makeLink({
                // Configure the text and click behavior of the link
                text: 'Click Here',
                click: (e: MouseEvent, ctx: wjcGrid.ICellTemplateContext) => {
                  const rowData: any = ctx.item as any;
                  // Check if the row has valid errors to download
                  if (rowData?.status_desc?.toUpperCase() === 'FAILED' && rowData?.errors?.length) {
                    this.downloadErrorJson(rowData, `error_${rowData.transaction_log_details_id}`);
                  }
                },
                attributes: {
                  class: 'text-blue-600 underline', // Add custom styles to the link
                },
              }).call(this, ctx, cell);
            },

    Here’s a sample for your reference demonstrating the same - https://stackblitz.com/edit/angular-ivy-2ekw6jp6?file=src%2Fapp%2Fapp.component.ts

    In case, you face any issues, please let us know.

    Regards

  • Posted 16 April 2025, 3:30 am EST

    Hi! Vivek,

    Thank you for your solution it worked well,

    Just a small correction:

    [code] cellTemplate: (ctx: wjcGrid.ICellTemplateContext, cell: HTMLElement | undefined) => {

    const item: IZPublishSummaryData = ctx.item as IZPublishSummaryData;

    // Check if the cell should display a link

    const shouldShow: boolean = item?.status_desc?.toUpperCase() === ‘FAILED’ && item?.errors?.length > 0;

    if (!shouldShow) {

    return ‘’; // Return an empty string for empty cells

    }

            // Display "Click Here" when conditions are met
            return CellMaker.makeLink({
              // Configure the text and click behavior of the link
              text: 'Click Here',
              click: (e: MouseEvent, ctx: wjcGrid.ICellTemplateContext) => {
                const rowData: IZPublishSummaryData = ctx.item as IZPublishSummaryData;
                // Check if the row has valid errors to download
                if (rowData?.status_desc?.toUpperCase() === 'FAILED' && rowData?.errors?.length) {
                  this.downloadErrorJson(rowData, `error_${rowData.transaction_log_details_id}`);
                }
              },
              attributes: {
                class: 'text-blue-600 underline' // Add custom styles to the link
              }
            })(ctx, cell);
          }[/code]
    

    for The call method at the end (.call(this, ctx, cell)) might be unnecessary because CellMaker.makeLink already handles the context internally i guess so, Instead, we should use it directly. calling we can directly use (ctx, cell) isn’t it. Please correct me if it will have any performance issue

  • Posted 17 April 2025, 12:17 am EST

    Hi Ratnesh,

    We are glad that the issue is resolved now. Regarding the ‘call’ method, you are correct, you can directly call the CellMaker.makeLink method, you’ll not have any performance impact.

    Regards

Need extra support?

Upgrade your support plan and get personal unlimited phone support with our customer engagement team

Learn More

Forum Channels