SlickGrid anyone?



  • Hi @all,

    my pain in the arse is this:
    readonly SlickGrid with some bells and whistles (sorting, column_headers with search, heavy formatting on cells and rows, etc)

    (I haven't figured out how to get a working jsfiddle or somesuch with this so please bear with me)
    origin: http://6pac.github.io/SlickGrid/examples/example-optimizing-dataview.html
    added some features & blah and eded up with this grid:
    58c2426e-3845-4fdf-9750-3f4185d8a235-grafik.png

    added some shite re "handle filtering" and all was well.. until somebody noticed that the css applied per row seems to be stick ..sticky.., e.g.:

    If one applies "1" as filter to column "% complete":
    6033ea25-4421-4225-9bdc-b4533473cad7-grafik.png

    -> Task 2 -which was shown as bold in the unfiltered grid is now "not bold" and it seems to me that <whatever slickgrid does here> is ..sticky.. and does not reflect any changes caused by applying <column-filter>

    Basically my question is: how does one re-apply row-based formatting if <grid> changes 'cos column-filters were applied?

    Repro if a kind|curious mind has an itch to scratch (/meesa too dumb for fiddle, remenber):
    -) download & unzip a file from https://github.com/6pac/SlickGrid/releases, anything recent should work (includes...), I'm using 2.4.14 here.
    -) plonk into ../examples and run it
    NOTE: the data shown in <grid> is random!

    my humble repro-thingy in all it's glory, focus was to include everything within a single file:

    <!DOCTYPE HTML>
    <html>
    <head>
      <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
      <link rel="shortcut icon" type="image/ico" href="favicon.ico" />
      <title>SlickGrid example: Optimizing DataView</title>
      <link rel="stylesheet" href="../slick.grid.css" type="text/css"/>
      <link rel="stylesheet" href="../css/smoothness/jquery-ui-1.11.3.custom.css" type="text/css"/>
      <link rel="stylesheet" href="../controls/slick.pager.css" type="text/css"/>
      <link rel="stylesheet" href="examples.css" type="text/css"/>
      <style>
        .cell-title {
          font-weight: bold;
        }
    	
    	.bold-row {
    		font-weight: 800;
    		color: black;
    	}
    	
      </style>
    </head>
    <body>
    <div style="position:relative">
      <div style="width:600px;">
        <div class="grid-header" style="width:100%">
          <label>SlickGrid</label>
        </div>
        <div id="myGrid" style="width:100%;height:500px;"></div>
        <div id="pager" style="width:100%;height:20px;"></div>
      </div>
    
      <div class="options-panel">
        <p>Original: example-optimizing-dataview.html</p>
      </div>
    </div>
    
    <script src="../lib/jquery-1.11.2.min.js"></script>
    <script src="../lib/jquery-ui-1.11.3.min.js"></script>
    <script src="../lib/jquery.event.drag-2.3.0.js"></script>
    
    <script src="../slick.core.js"></script>
    <script src="../slick.formatters.js"></script>
    <script src="../slick.grid.js"></script>
    <script src="../slick.dataview.js"></script>
    <script src="../plugins/slick.rowselectionmodel.js"></script>
    
    <script>
      var dataView;
      var grid;
      var data = [];
      var gridFilters = [];
      var columns = [
        {id: "sel", name: "#", field: "num", behavior: "select", cssClass: "cell-selection", width: 40, resizable: false, selectable: false },
        {id: "title", name: "Title", field: "title", width: 120, minWidth: 120},
        {id: "duration", name: "Duration", field: "duration"},
        {id: "%", name: "% Complete", field: "percentComplete", width: 80, resizable: false /*, formatter: Slick.Formatters.PercentCompleteBar*/},
        {id: "start", name: "Start", field: "start", minWidth: 60},
        {id: "finish", name: "Finish", field: "finish", minWidth: 60},
        {id: "effort-driven", name: "Effort Driven", width: 80, minWidth: 20, maxWidth: 80, cssClass: "cell-effort-driven", field: "effortDriven", formatter: Slick.Formatters.Checkmark}
      ];
    
      var options = {
        multiColumnSort: true,
        numberedMultiColumnSort: true,
        tristateMultiColumnSort: true,
        sortColNumberInSeparateSpan: true,
        explicitInitialization: true,
        showHeaderRow: true,
        headerRowHeight: 25,
        rowHeight: 25
        /* ORI
    	editable: false,
        enableAddRow: false,
        enableCellNavigation: true
    	*/
      };
    
      var percentCompleteThreshold = 0;
      var prevPercentCompleteThreshold = 0;
      var h_runfilters = null;
    
      function myFilter(item, args) {
    	for (var columnId in gridFilters) {
    		if (columnId !== undefined && gridFilters[columnId] !== "") {
    			var c = grid.getColumns()[grid.getColumnIndex(columnId)];
    			var cellValue = "" + item[c.field];
                var searchFor = gridFilters[columnId];
    			
                if (cellValue === "" || cellValue == null) {
                    return false;
                }
    
                if ($.isNumeric(searchFor) === false) {
                    searchFor = searchFor.toLowerCase();
                }
    
                if ($.isNumeric(cellValue) === false) {     
                    cellValue = cellValue.toLowerCase();
                }
    
                // handling of dates etc omitted!
    
                if (cellValue.indexOf(searchFor) < 0) {
    				console.log("exit");
                    return false;
                } 		
    		}
    	}
    	return true;
      }
    
      function DataItem(i) {
        this.num = i;
        this.id = "id_" + i;
        this.percentComplete = Math.round(Math.random() * 100);
        this.effortDriven = (i % 5 == 0);
        this.start = "01/01/2009";
        this.finish = "01/05/2009";
        this.title = "Task " + i;
        this.duration = "5 days";
      }
    
    
      $(function () {
        // prepare the data
        for (var i = 0; i < 50; i++) {
          data[i] = new DataItem(i);
        }
    
        dataView = new Slick.Data.DataView({ inlineFilters: true });
    	dataView.getItemMetadata = function (row) {
                    if (data.length === 0)
                        return null;
                    var item = data[row];
                    var cssClasses = [];
    
                    if (item.percentComplete > 50 || item.percentComplete < 10) {
                        cssClasses.push("bold-row");
                    }
    
                    if (cssClasses.length > 0) {
                        var classes = cssClasses.join(" ");
                        return { cssClasses: classes };
                    }
                    return null;
                };
    	
        grid = new Slick.Grid("#myGrid", dataView, columns, options);
    	
    	grid.setSelectionModel(new Slick.RowSelectionModel());
    	
    	grid.onHeaderRowCellRendered.subscribe(function (e, args) {
    		if (args.column.id !== "rowCounter" && args.column.id !== "priority") {
    			$(args.node).empty();
    
    			$("<input type='text' class='slick-headerrow-input'>")
    				.data("columnId", args.column.id)
    				.val(gridFilters[args.column.id])
    				.appendTo(args.node);
    		}
    	});
    		
    	$(grid.getHeaderRow()).on("change keyup", ":input", function (e) {
    		var columnId = $(this).data("columnId");
    		if (columnId != null) {
    			gridFilters[columnId] = $.trim($(this).val());
    			dataView.refresh();
    		}
    	});
    
        // wire up model events to drive the grid
        dataView.onRowCountChanged.subscribe(function (e, args) {
          grid.updateRowCount();
          grid.render();
        });
    
        dataView.onRowsChanged.subscribe(function (e, args) {
          grid.invalidateRows(args.rows);
          grid.render();
        });
    
        // initialize the model after all the events have been hooked up
    	grid.init();
    	
        dataView.beginUpdate();
        dataView.setItems(data);
        dataView.setFilter(myFilter);
        dataView.setFilterArgs(0);
        dataView.endUpdate();
      })
    </script>
    </body>
    </html>
    

    Any Ideas from the trusty community?


  • Notification Spam Recipient

    @iKnowItsLame said in SlickGrid anyone?:

    Any Ideas from the trusty community?

    Not sure about "trusty", but have you tried calling grid.invalidate() after setting the filter?

    It is kinda odd that it's not correctly applying the css classes according to the getItemMetadata function on filter.

    Telling it to re-render the grid should (hopefully) bodge that to work again.



  • @Tsaukpaetra grid.invalidate() .. where should I apply this?

    BTW: getting an answer within 15 minutes without causing a flamewar is 'trusty' in my book :trollface:


  • Notification Spam Recipient

    @iKnowItsLame said in SlickGrid anyone?:

    @Tsaukpaetra grid.invalidate() .. where should I apply this?

    BTW: getting an answer within 15 minutes without causing a flamewar is 'trusty' in my book :trollface:

    I just so happened to be on.

    You should apply it after the filter is applied. Perhaps tie it onto onRowsChanged ?



  • @iKnowItsLame The problem is, you're basing the condition to bold a row against the same index in the unfiltered data, not against the filter data in the grid. Your dataView.getItemMetadata function should be:

    
    	dataView.getItemMetadata = function (row) {
                    if (dataView.getLength() === 0)
                        return null;
                    var item = dataView.getItem(row);
                    var cssClasses = [];
    
                    if (item.percentComplete > 50 || item.percentComplete < 10) {
                        cssClasses.push("bold-row");
                    }
    
                    if (cssClasses.length > 0) {
                        var classes = cssClasses.join(" ");
                        return { cssClasses: classes };
                    }
                    return null;
                };
    
    

  • Notification Spam Recipient

    @ChaosTheEternal said in SlickGrid anyone?:

    @iKnowItsLame The problem is, you're basing the condition to bold a row against the same index in the unfiltered data, not against the filter data in the grid. Your dataView.getItemMetadata function should be:

    Oh yeah, I didn't even see that. Good point.



  • @Tsaukpaetra "Perhaps tie it onto onRowsChanged ?"
    that doesn't do anything :-/,

    /it ain't that fulgy kind of bug but it just seems to trigger something within my spectrum and annoys me somewhat.


  • Notification Spam Recipient

    @iKnowItsLame Yeah, Try @ChaosTheEternal 's idea.



  • @ChaosTheEternal my momma told me that I should not fondle random people on the internet but imagine you wre hugged just right now. ;-)

    -> works!

    And this is why I said 'trusty'.

    Thankyou!



  • @ChaosTheEternal said in SlickGrid anyone?:

    @iKnowItsLame The problem is, you're basing the condition to bold a row against the same index in the unfiltered data, not against the filter data in the grid. Your dataView.getItemMetadata function should be:

    
    	dataView.getItemMetadata = function (row) {
                    if (dataView.getLength() === 0)
                        return null;
                    var item = dataView.getItem(row); **//<- THIS is the trick, my code used "data[row];"**
                    var cssClasses = [];
    
                    if (item.percentComplete > 50 || item.percentComplete < 10) {
                        cssClasses.push("bold-row");
                    }
    
                    if (cssClasses.length > 0) {
                        var classes = cssClasses.join(" ");
                        return { cssClasses: classes };
                    }
                    return null;
                };
    
    


  • I wish I had heard about this grid before. There was a project in which I used jsgrid until boss demanded being able to change the selected rows with the arrow keys and add keyboard commands (press insert to add row, enter to edit row and delete to delete row) so I had to make a shittier version of jsgrid with keyboard support which is still kinda broken because focusing on non-form html elements is very fragile and kinda broken.


Log in to reply