Passing a global variable to state save? Draw?

Passing a global variable to state save? Draw?

janetcljanetcl Posts: 37Questions: 4Answers: 0

Hello, I am working on my application and I am wondering if there is a way to pass an altered Javascript global variable (unrelated to the table) to a row callback and columns.render() call from the initial loading of the table to the next draw. I am using checkboxes to show and hide columns, but this changes the data within the tables, so I am maintaining an array of booleans that indicate whether or not to show a column (I am not using buttons because I need to check the visibility of each column upon redrawing). I use this array of booleans to alter the data to be shown in the table upon redrawing. Is there a method that would be helpful that I am missing? I've been looking at the DataTables for a week now trying to resolve this problem, so any help would be greatly appreciated.

Please let me know if you need any additional information from me. Thanks.

This question has an accepted answers - jump to answer

Answers

  • janetcljanetcl Posts: 37Questions: 4Answers: 0

    Alternatively, is it possible to access column.visible() from a row callback?

  • allanallan Posts: 61,438Questions: 1Answers: 10,052 Site admin

    Hi,

    I'm afraid I don't quite understand what you are trying to do. Are you able to illustrate with an example please?

    Thanks,
    Allan

  • janetcljanetcl Posts: 37Questions: 4Answers: 0

    I am making an app that compares product prices among sellers. I have checkboxes that allow the user to show / hide columns for the sellers. In another column (not hideable), I have my company's price, which includes displayed data from a hidden column that indicates the discount (the price difference between my company and the lowest price of the sellers whose columns are visible). Here is a visual:

    For each row, of the visible sellers, the cell with the lowest price will be highlighted green, and the discount will be computed using the "green" price and the CDO price. The issue is that this constantly changes depending on which columns are visible. I tried to use a global array of booleans to store whether or not a sellers' column was visible and refer back to the array when 1. rendering the CDO column (to determine the discount) and 2. determining which cell to highlight green.

    When I tried the array method, the table would simply re-draw itself and the array would be re-initialized to showing all columns (all true).
    As an alternate approach, in a row callback function, I tried to call table.column(i).visible() but I receive an error in the console. So, is there any way to check for individual column visibility upon re-drawing the table?

    Again, please let me know if you need any more information from me. Thanks.

  • janetcljanetcl Posts: 37Questions: 4Answers: 0

    As a note, the image is not accurate because the green highlighting is off. This is because I am in the process of trying to resolve the re-drawing issue; the coloring works well upon initialization (so $15.66, $56.86, and $75.01 would be highlighted green).

  • allanallan Posts: 61,438Questions: 1Answers: 10,052 Site admin

    Ah! Thanks for the extra details. rowCallback is currently the way to do this. It will be called whenever the data in the table is updated, so you can modify the cell classes as needed.

    What was the error you got when using that method? Also what code were you using inside it?

    Allan

  • janetcljanetcl Posts: 37Questions: 4Answers: 0

    This is my error when I call table.column(i).visible() :

    Uncaught TypeError: Cannot read property 'column' of undefined
    at jQuery.fn.init.rowCallback (localhost/:316)
    at datatables.js:6648
    at Function.map (jquery-3.3.1.js:443)
    at _fnCallbackFire (datatables.js:6647)
    at _fnDraw (datatables.js:3478)
    at _fnReDraw (datatables.js:3562)
    at _fnInitialise (datatables.js:4744)
    at loadedInit (datatables.js:1306)
    at loaded (datatables.js:6424)
    at _fnLoadState (datatables.js:6435)

    When I try calling this.column.visible(i), I get this error:
    Uncaught TypeError: this.column is not a function

    When I try calling column(i).visible, I get this error:
    Uncaught ReferenceError: column is not defined

    This is the code in the callback function:

    // determine which seller has the best price and change the background color accordingly
                      'rowCallback': function(row, data, index){
                          // find the brand with the best price
                          var lowestPrice = Infinity;
                          var sellerWithBestPrice;
                          for (var i = 0; i < data.bestDeal.length; i++) {
                            if (data.bestDeal[i] != null) {
                              if (data.bestDeal[i].price < lowestPrice) {
                                lowestPrice = data.bestDeal[i].price;
                                sellerWithBestPrice = data.bestDeal[i].brandNumber + 4;
                              }
                            }
                          }
                          if (sellerWithBestPrice == null) {
                            console.log("null best price at barcode: ", data.barcode);
                          }
                          //make sure that seller with best price exists (not all null values)
                            // note that brand numbers are 1, 2, 3, 4, 5
                            // color the appropriate cells green (check for multiples too)
                            for (var i = 0; i < data.bestDeal.length; i++) {
                              if (data.bestDeal[i] != undefined) {
                                if (data.bestDeal[i].price == data.bestDeal[sellerWithBestPrice - 4].price) {
                                  var dealCell = 2;
                                  for (var j = 0; j < i; j++) {
                                    console.log("j: " + j + this.column( j + 2 ).visible());
                                    if (column( j + 2 ).visible() == true) {
                                      dealCell++;
                                    }
                                  }
                                  // var dealCell = data.bestDeal[i].brandNumber + 2;
                                  $(row).find(`td:eq(${dealCell})`).css('background-color', '#b9f6ca');
                                  $(row).mouseenter(function() {
                                    $(row).find(`td:eq(${dealCell})`).css("background-color", "#8cf9aa");
                                  }).mouseleave(function() {
                                    $(row).find(`td:eq(${dealCell})`).css("background-color","#b9f6ca");
                                  });
                                }
                              }
                            }
    }
    
  • allanallan Posts: 61,438Questions: 1Answers: 10,052 Site admin
    Answer ✓

    this.api() is how to get an API reference in the rowCallback method. e.g.

    rowCallback: function ( row, data, index ) {
      var api = this.api();
    
      ...
      api.column( ... ).visible();
    }
    

    Allan

  • janetcljanetcl Posts: 37Questions: 4Answers: 0

    Amazing! That solved most of the problem. Is there a way to call this.api() in a call to "render"? I get the error:
    Uncaught TypeError: this.api is not a function
    at render

    Thanks again!

  • janetcljanetcl Posts: 37Questions: 4Answers: 0

    Note that I am calling "render" within the "columnDefs" array.

  • janetcljanetcl Posts: 37Questions: 4Answers: 0

    This is so that I can manipulate the data in the CDO column to show the updated discount -- the row callback has fixed the coloring issue, but now I need to change the discount appropriately and resort the column. If it is not possible to access the datatable API from "render," is it possible to manipulate which data is displayed and sorted in the row callback?

  • janetcljanetcl Posts: 37Questions: 4Answers: 0

    I just resolved this issue by using:

    "render": function ( data, type, row, meta ) {
                              var settings = meta.settings;
                              var api = new $.fn.dataTable.Api( settings );
    

    Based on this discussion: https://datatables.net/forums/discussion/comment/88687/#Comment_88687

    Thanks so much for all of your help!! My table works beautifully now :)

  • allanallan Posts: 61,438Questions: 1Answers: 10,052 Site admin

    I wouldn't normally recommand using the API in the render callback as there is a bit of overhead involved. What are you doing in it?

    Allan

This discussion has been closed.