Data table hangs browser when Large data in the table

Data table hangs browser when Large data in the table

amit_routadigitalamit_routadigital Posts: 2Questions: 1Answers: 0
edited April 9 in Free community support

Data table hangs browser when Large data in the table
Datatable search pane with large data set hangs for few second .
My project using react(fe) + node.js(be)

scenarioTable = new DataTable(tableRef?.current, {
      fixedColumns: {
        leftColumns: 2,
        left: 1,
        start: 2,
      },
      fixedHeader: true,
      scrollX: 300,
      scrollY: ((windowDimensions?.height/1.5)-100),
      scrollCollapse: true,
      scrollInfinite: true,
      colReorder: colReorder_options,
      data: scenarioData,
      language: {
        loadingRecords: " ",
        processing: "Loading...",
      },
      buttons: html5Buttons(),
      destroy: true,
      pageLength: 100,
      lengthMenu: [
        [10, 25, 50, 100, 500, -1],
        ["10", "25", "50", "100", "500", "Show all"],
      ],
      aaSorting: [],
      searchPanes: {
        layout: 'columns-4',
        orderable: false,
        threshold: 1,
      },
      dom: "PBfrtip",
      columns: scenarioColumnsHeaders?.map((element, index) => {
        // console.log(element, "=====element")
        element.render = function (data, type, row) {
          if (
            type === "display" &&
            data != null &&
            typeof data === "string"
          ) {
            data = data.replace(/<(?:.|\\n)*?>/gm, "");
            data = data.replaceAll('"', "");
            const dataTitle = data;
            data = data.split(",").join(",<br/>")
            if (data.length > 100 && data[element.data] == 'Business Capability') {
              return `<span class='show-ellipsis text-wrapped' data-title='${dataTitle}'>${data.substr(
                0,
                100
              )} ...</span><span class='no-show'>${data.substr(100)}</span>`;
            } else if (data.length > 50) {
              return `<span class='show-ellipsis text-wrapped' data-title='${dataTitle}'>${data.substr(
                0,
                50
              )} ...</span><span class='no-show'>${data.substr(50)}</span>`;
            } else {
              return data || "";
            }
          } else {
            return data || "";
          }
        }

        return element;
      }),
      select: {
        style: "multi",
        selector: "td:first-child",
      },
      initComplete: function (settings, json) {
        var api = this.api();
        replacePlaceholder();
        // this.api().searchPanes.rebuildPane();
        $('#int-app-table').on('dblclick', 'tbody td', async function (e) {
          let container = $("div.comment-content");
          container.remove();
          message.destroy()
          if (UserService.hasRole(['Admin', 'Editor'])) {
            setDefaultSelectValue([]);
            setModalSelectOpen(false);
            setModalTextareaOpen(false);
            setInputValue('');
            let columnIndex = $(this).index();

            var rowIndex = $(this).closest('tr').index();
            let row = scenarioTable.row(this).data();
            let scenarioId;
            if (row && row?.DT_RowId) {
              scenarioId = row.DT_RowId.split("_")[2];
            }
            let columnId = null;
            let availableColumnId = null;
            const column = scenarioColumns[columnIndex - 1];
            if (scenarioColumnsResponse?.length != 0) {
              for (let item of scenarioColumnsResponse) {
                if (item?.columnName == column?.label) {
                  columnId = item.id;
                  availableColumnId = item.availableColumnId;
                  break
                }
              }
            }
            let value = $(this).text();
            if ($(this).find('span.text-wrapped').length !== 0) {
              value = $(this).find('span.text-wrapped').attr('data-title');
            }
            let obj = {
              scenarioId: scenarioId,
              rowIndex: rowIndex,
              columnId: columnId,
              availableColumnId: availableColumnId,
              column: column,
              row: row,
            }

            setSelectSubmitData(obj)
            if (column?.type == "select") {
              const dropdownVal = await ScenarioServices.getScenarioDropdownValue({
                "columnId": availableColumnId,
              })
              if (dropdownVal.data) {
                setOptions(dropdownVal.data)
              } else {
                setOptions(column?.ipOpts)
              }
              let trimmedValues;
              if (value.includes(',')) {
                trimmedValues = value.split(',').map(item => item.trim());
                setDefaultSelectValue(trimmedValues)
              } else {
                trimmedValues = [value];
                setDefaultSelectValue(trimmedValues)
              }
              setModalSelectOpen(true)

            } else {
              setTextareaValue(value);
              setModalTextareaOpen(true)
            }
          } else {
            message.error("You are not authorised to update the data!")
          }
        })

        $('#int-app-table').on('contextmenu', 'tbody td', function (event) {
          message.destroy()
          if (UserService.hasRole(['Admin', 'Editor'])) {
            setSelectSubmitData({})
            var columnIndex = $(this).index();
            let row = scenarioTable.row(this).data()
            if (row) {
              let scenarioId = row.DT_RowId.split("_")[2];
              let rowId = row.DT_RowId.split("_")[1];
              let columnId = null;
              let availableColumnId = null;
              const column = scenarioColumns[columnIndex - 1];
              if (scenarioColumnsResponse?.length != 0) {
                for (let item of scenarioColumnsResponse) {
                  if (item?.columnName == column?.label) {
                    columnId = item.id;
                    availableColumnId = item.availableColumnId;
                    break
                  }
                }
              }
              setSelectSubmitData({
                rowId: rowId, columnId: availableColumnId, scenarioId: scenarioId
              })
              show({
                event,
                props: {
                  key: 'value'
                }
              })
            }
          } else {
            message.error("You are not authorised to apply comment!")
          }

        })

        $('.dataTables_scrollHead').css({
          'overflow-x': 'scroll'
        }).on('scroll', function (e) {
          var scrollBody = $(this).parent().find('.dataTables_scrollBody').get(0);
          scrollBody.scrollLeft = this.scrollLeft;
          $(scrollBody).trigger('scroll');
        });

      },
      createdRow: function (row, data, dataIndex) {
        if (data['column_base']) {
          $(row).css('background-color', '#d8e5f1');
          $(row).css('font-weight', '600');
        }
        for (let key in data) {
          if (key.includes('_comment') && data[key] && data[key].length > 0) {
            const columnIndex = getColumnIndexByKey(scenarioColumnsHeaders, key.replace('_comment', ''));
            if (columnIndex !== -1) {
              const cell = $(row).find('td:eq(' + columnIndex + ')');
              cell.addClass('comment-added');

              const commentData = data[key];
              const commentContent = commentData.map(item => {
                const formattedDate = new Date(item.createdAt).toLocaleDateString('en-GB', {
                  day: '2-digit',
                  month: '2-digit',
                  year: 'numeric'
                });

                return `
                            <strong>User:</strong> ${item.userEmail ? item.userEmail : '-'}<br>
                            <strong>Comment:</strong> ${item.comment}<br>
                            <strong>Date:</strong> ${formattedDate}<br>
                            <hr>
                            `;
              }).join('');


              // Add Bootstrap popover
              cell.attr('data-toggle', 'popover');
              cell.attr('data-html', 'true'); // Enable HTML content
              cell.attr('data-content', commentContent);
              // cell.attr('data-trigger', 'hover');
              cell.attr('data-placement', "bottom");
              // cell.popover();
            }
          }
          if (key.includes('_difference') && data[key]) {
            const columnIndex = getColumnIndexByKey(scenarioColumnsHeaders, key.replace('_difference', ''));

            if (columnIndex !== -1) {
              const cell = $(row).find('td:eq(' + columnIndex + ')');
              cell.css('color', '#ea0505');
              cell.css('font-style', 'italic')
            }
          }
        }
      },
      searchDelay: 350,
      drawCallback: function (settings) {
        let searchText = $('#int-app-table_filter input[type=search]').val();
        if (settings?.iDraw >= 2) {
          setHighlight(searchText);
        }


        $('.paginate_button.next:not(.disabled)', this.api().table().container())
          .on('click', function () {
            alert('next');
          })
      }
    });

Edited by Colin - Syntax highlighting. Details on how to highlight code using markdown can be found in this guide.

Answers

  • colincolin Posts: 15,158Questions: 1Answers: 2,587

    When you say "large data", how large are we talking? For DOM source data, which your config suggests you're using, the recommendation is up to 5k rows.

    This section of the FAQ should help, it discusses various techniques to improve performance.

    Colin

  • amit_routadigitalamit_routadigital Posts: 2Questions: 1Answers: 0
    edited April 9

    Thanks for quick reply @colin .

    But still it is not working properly as i used these following options.Please guide me if i am doing something worng.

    paging:false,
    orderClasses: false,
    deferRender: true,
    scrollInfinite: true,
    with ajax and without ajax
    

    ``` table's html

              <table
                id="int-app-table"
                ref={tableRef}
                className="table display nowrap pt-1 table-bordered"
                style={{ width: "100%" }}
              >
              </table>
    

    ```

    with page length 25 it is working fine but with page length 100 browser hangs.

  • kthorngrenkthorngren Posts: 20,361Questions: 26Answers: 4,777
    edited April 9

    From Colin:

    When you say "large data", how large are we talking?

    but with page length 100 browser hangs.

    Do you get errors in the browser's console?

    What exactly happens, ie, can you click elements outside of Datatables?

    Does it hang on initial loading or when interacting with the Datatable?

    Can you post a link to your page or test case replicating the issue so we can help debug?
    https://datatables.net/manual/tech-notes/10#How-to-provide-a-test-case

    Kevin

Sign In or Register to comment.