Export Timing out issue

clock October 31, 2016 01:05 by author htmltreegrid

Recently had an issue reported by a long time customer. 

 

 

While using Export to excel in Htmltreegrid, We have implemented “Excel2007” option  to export gridData in “.xls” format.

We are implementing this using Excel2007Exporter.js file(see attached) and added following code in our controller file in onGridCreationComplete function.

 

$scope.onGridCreationComplete = function(evt) {

                                                                                                                                var grid = evt.target;

                                                                                                                                grid.excelOptions.exporters = exporters = [new flexiciousNmsp.CsvExporter(), new flexiciousNmsp.DocExporter(),

                                                                                                                                new flexiciousNmsp.HtmlExporter(),new flexiciousNmsp.XmlExporter(),new flexiciousNmsp.TxtExporter(),

                                                                                                                                 new flexiciousNmsp.Excel2007Exporter()

                                                                                                                                 ];

                                                                                                                                 grid.excelOptions.enableLocalFilePersistence=false;

                                                                                                                                grid.validateNow();

                                                                                                                };

 

 

 

But while Exporting the data of the grid which is having more than large records(1000+ records), It redirects  to Flexicious homepage and shows error message whithout generating excel.

 

Please suggest on this.

=========================================================

Answer :

This customer (like many others) was using sample code from an old version of the product that did not have support for file saver. It was using the flexicious server echo. When you do a export , we basically build a string on the client application. If Flash player is available, we will use it via the downloadify library. If not, we need to go through the traditional http File Buffering process. So what we do is this : We build the excel/word/html string, and send it to the server, which simply writes it back, in addition to setting the content type. Now, we advise that you implement your own url to buffer this string back, but do provide our own url - the one mentioned above to perform the buffering. There is more information here : http://blog.htmltreegrid.com/post/Excel-Word-and-Html-Export-and-the-Echo-URL.aspx 

However, with the newer versions, we have added support for file saver. On modern browsers, you can do file save without the need for having flash. So the download mechanism will check to see if filesaver exists and is supported, if so, will use that. If it is not there or is not supported, it will fall back to flash. All you have to do is to use the new release and include FileSaver.js. If you include our PDF support, FileSaver is automatically included.

<script type="text/javascript" src="http://htmltreegrid.com/demo/external/js/thirdparty/jspdf-combined.js"></script>

You can also import filesaver independently:

https://github.com/eligrey/FileSaver.js/ 

Complete working example below:

index.zip (2.74 kb)



Copy Cell Issue with custom HTML in cells

clock October 5, 2016 03:57 by author htmltreegrid

As most of you know, the grid provides an extremely convenient mechanism to write out custom HTML in cells, labelFunction and labelFunction2. This gives you complete control over what html you want to appear within each cell. However, with this flexibility comes a little bit of a issue in that the same code is executed when the grid renders the cell, or the cell export or copy mechanism inspect the cells to figure out the text to export or to copy. 

One of our customers was trying to implement the copy cell functionality described in this blog post:

http://blog.htmltreegrid.com/post/Adding-Custom-Right-Click-functionality-to-HTMLTreeGrid.aspx 

However, when they had custom HTML in the cell, there were two issues they encountered:

1.       While using label-Function2, and try to use this Copy cell it is giving below error, And it is not doing anything :

minified-compiled-jquery.js:1300 Uncaught TypeError: Cannot read property 'implementsOrExtends' of null

2.       While using Copy Table functionality, It is giving below error, And it is not doing anything:

minified-compiled-jquery.js:472 Uncaught ReferenceError: isIncludedInExport is not defined

 

 In In a nutshell, the problem is this - when you do copy cell, we need to identify which cell your mouse is on. We use the mouse event target to find out which FlexDataGridCell object the mouse event dom element belongs to. In this case, since we have custom HTML within the cell, we need to navigate to the DIV domelement first and then use that to get to the FlexDataGridCell object. Attached is a working test case that demonstrates fix for the above issue. 

HTML5_FleixiciousGrid.zip (8.44 kb)



Some Recent FAQs

clock October 4, 2016 06:07 by author htmltreegrid

Recently had a couple interesting questions:

Question : I am using flexicious HTMLTree grid in one of my project and I am not able to figure how to retrieve filtered rows anytime on grid. I need all rows which are actually filtered and not just rows appearing on screen at any instant. Please let me know how can I achieve that and it will great if you could share sample example of it.

Answer :   var filterData = grid.getFilteredPagedSortedData({},true,false,false,false);

 

Question : We are using HTMLTreeGrid with angularJS.  In our applications we have added buttons to our grid using the ToolBarActions but need more control when to enable a button than simply saying a row has been picked at a level.  For example, we only want to enable the button based on data in the selected row.  Is that possible?  Can you send an example how to do this?  Or do we need to create a Custom PagerControl to do this?  And how easy is it to extend the PagerControl to additional functions?

It is very easy to extend the pager control:

http://blog.htmltreegrid.com/post/How-to-Customize-the-Pager-(Toolbar)-Export-Options-Settings-and-Save-Settings-Popups.aspx

The toolbar actions are built within the pager control. You can do something like this:

 toolbarActionValidFunction="isValidToolbarAction" 

Here is the default implementation:

/**
 * Evaluates whether the given toolbar action is valid or not.
 *
 * If toolbarActionValidFunction is not null, returns the result of the function passing in the given ToolbarAction.
 * Else returns true.
 * @method isToolbarActionValid
 */
isToolbarActionValid = function (action, currentTarget, extendedPager) {
    if (action.requiresSingleSelection) {
        if (this.getSelectedKeys().length == 1) {
            var appliesToLevel = action.level;
            var itemLvl = this.getLevelForItem(this.getSelectedObjects()[0]);
            if (appliesToLevel == -1 || (itemLvl && (itemLvl.getNestDepth() == appliesToLevel)))
                return true;
            else
                return false;
        }
        return false;
    } else if (action.requiresSelection) {
        return this.getSelectedKeys().length > 0;
    }
    return true;
};
Finally, two attached examples demonstrate how to accomplish this with Angular JS:

angular (1).html (5.12 kb)

Index_hierarchy.html (6.24 kb)

And can you explain how to set the grid so picking a top level row does not automatically pick all nested next levels rows?  We can pick a row from the next level row and it does not auto pick the parent row.  We need the user to explicitly pick the nested rows even when the parent row is selected.

 

è     Just set enableSelectionCascade to false. 



How to use third party components in HTMLTreeGrid

clock July 5, 2016 07:06 by author htmltreegrid

This is a question that has come up before, and its a hard one to answer. As you are aware, we provide API hooks to give you complete control over the contents of each cell. There are some easy way to do this - for example, you can simply return some custom HTML in a labelFunction, and even make it interactive, like we show in this blog post: http://blog.htmltreegrid.com/post/How-to-add-custom-interactive-html-from-a-labelFunction.aspx 

However, the question becomes, how about when you have to use custom third party components. While we cannot guarantee the product will work with every single third party component, nor can we offer support for components that we have not authored, we certainly can show you how this can be done with a sample component. For this example, we are going to use the powerful and very popular select2 jquery auto complete component. 

Let's dive into the code:


/**
* Flexicious
* Copyright 2011, Flexicious LLC
*/
(function(window)
{
"use strict";
var AutoCompleteRenderer, uiUtil = flexiciousNmsp.UIUtils, flxConstants = flexiciousNmsp.Constants;
/**
* A CheckBoxRenderer is a custom item renderer, that defines how to use custom cells with logic that you can control
* @constructor
* @namespace flexiciousNmsp
* @extends UIComponent
*/
AutoCompleteRenderer=function(){
//make sure to call constructor
flexiciousNmsp.UIComponent.apply(this,["div"]);//second parameter is the tag name for the dom element.



var html='<select class="js-example-basic-single"> <option value="AL">Alabama</option><option value="AL">Alaska</option><option value="CO">Colorado</option></select>';
this.domElement.innerHTML=html;
this.select = this.domElement.firstChild;
var $eventSelect =$(this.select);
$eventSelect.select2();
$eventSelect.on("change", this.onChange.bind(this));

/**
* This is a getter/setter for the data property. When the cell is created, it belongs to a row
* The data property points to the item in the grids dataprovider that is being rendered by this cell.
* @type {*}
*/
this.data=null;

};
flexiciousNmsp.ItemRenderers_AutoCompleteRenderer = AutoCompleteRenderer; //add to name space
AutoCompleteRenderer.prototype = new flexiciousNmsp.UIComponent(); //setup hierarchy
AutoCompleteRenderer.prototype.typeName = AutoCompleteRenderer.typeName = 'AutoCompleteRenderer';//for quick inspection
AutoCompleteRenderer.prototype.getClassNames=function(){
return ["AutoCompleteRenderer","UIComponent"]; //this is a mechanism to replicate the "is" and "as" keywords of most other OO programming languages
};

/**
* This is important, because the grid looks for a "setData" method on the renderer.
* In here, we intercept the call to setData, and inject our logic to populate the text input.
* @param val
*/
AutoCompleteRenderer.prototype.setData=function(val){
flexiciousNmsp.UIComponent.prototype.setData.apply(this,[val]);
var cell = this.parent; //this is an instance of FlexDataGridDataCell (For data rows)
var column = cell.getColumn();//this is an instance of FlexDataGridColumn.
if(this.data[column.getDataField()])
this.select.value=this.data[column.getDataField()];
};
/**
* This event is dispatched when the user clicks on the icon. The event is actually a flexicious event, and has a trigger event
* property that points back to the original domEvent.
* @param evt
*/
AutoCompleteRenderer.prototype.onChange=function(evt){

//in the renderer, you have the handle to the cell that the renderer belongs to, via the this.parent property that you inherit from flexiciousNmsp.UIComponent.

var cell = this.parent; //this is an instance of FlexDataGridDataCell (For data rows)
var column = cell.getColumn();//this is an instance of FlexDataGridColumn.
console.log('setting value to' + this.select.value)
this.data[column.getDataField()]=this.select.value;//we use the dom element to wire back the value to the data object.
};
//This sets the inner html, and grid will try to set it. Since we are an input field, IE 8 will complain. So we ignore it since we dont need it anyway.
AutoCompleteRenderer.prototype.setText=function(val){

};
}(window));

We are defining an itemRenderer here, that simply wraps a select2 component. In its constructor, we initalize it.
In the set data method, we populate it. And we listen for its change event, where we write the data back to the 
data provider.
Below is the complete running example:

third-party-item-renderer.html (7.22 kb)

 

And this is what this will look like:

 



Selected Index Question

clock June 9, 2016 20:49 by author htmltreegrid

Recently got a question about the selected index property.


the question read something like this


The function

grid.getSelectedIndex()

returns the actual index of the selected row, which is correct when no filter is set.

But if I set a filter (which, of course, reduces the amount of actually displayed data) this function returns still the same number, which is not correct.

Is there a function that returns the index of the selected row while considering any active filters?

For example: I have 10 rows in my grid. When I click on the 5th row then getSelectedIndex() returns 4 (because it’s a zero-based index).

But if I set a filter causing that just this one row is visible and the others rows are not visible anymore (grid.getTotalRecords returns 1), then by clicking on this row the function getSelectedIndex() still returns 4, but should now return 0.


===

The short answer to this question is that  it is possible to do it if you really want the selectedIndex, do grid.getFilteredPagedSortedData() and then do an indexOf grid.getSelectedItem() on that array.


 var filterCnt = grid.getFilteredPagedSortedData({},true,false,true);

  And then

 filterCnt.indexOf(grid.getSelectedItem())

 

The longer answer is a little more involved.  and the primary idea is if  in reality what you need is the item that is selected just use the getSelectedItem method.  we made a conscious decision to deviate from the way some other products store  the selected state of the grid.  depending on what you set as the value for your selectedKeyField,  we will either store the actual object that is selected or a key property on the object that is selected.  internally we never store the index of the object that selected.  this is always calculated.  this allows us to maintain selection regardless of the state of the data provider if it's filters sorted, or paged in any manner.

 

The selectedIndex is not a reliable method of identifying the selected object, because that index changes everytime you do a sort or a filter or page. In other words. If the selected index is on page 0, and you move to page 2, the selectedIndex means nothing because the object is no longer on the page. This gets further complicated when server paging is invovled. So our recommendation is always use grid.getSelectedItem instead of grid.getSelectedIndex, because majority of the time, you are using the index to get to the actual item anyway.



Calling methods on Angular Scope

clock May 31, 2016 02:03 by author htmltreegrid

Recently a few customers have asked the same question:

We are using HTMLTreegrid with angularJS. We are expecting code snippet with angularJS.

In angularJS controller we are unable to call scope function which mentioned in previous mail.

 

At Angular contoller

 

$scope.saveStatus= function(rowData, column){

                var data='<div ><a href="javascript:void(0);" class="launchEditor" ng-click= "updateStatus('+rowData+')"><i class="fa fa-check"></i></a></div>';

         return data;

       

 }

 

 

 

Answer is to get scope from the item being clicked.  

For example:

myCompanyNameSpace.ItemRenderers_getNextHTML=function(item,column){

                       

            return "<img src='resources/app/assets/next.png' class='custom-hover' onclick='itemClickEvent(this)' title='Go to Item Info'>";

 

};

 

itemClickEvent =function(item){

        var scope = angular.element(document.getElementById("MainWrap")).scope();

                

        scope.$apply(function () {

              var itemObj = item.parentNode.component.data;

              console.log("itmeObj "+ itmeObj);

              scope.gotoItemInfo(itmeObj);

            });

};

 

 

 



A couple of customer questions

clock May 12, 2016 03:54 by author htmltreegrid

Recently we had a couple of questions that we have had before, so publishing them for your reference:

 

We are using the new HTMLTreeGrid with AngularJS and are able to set the grid style as such as:

$scope.gridOptions = {
    styles: flexGrid.UIUtils.getThemeById('blue').styles,
    delegate: $scope };

Our user's need the ability to change their theme and want the grid to reflect their new selected them.  We hope to do this without rebuilding the grid by simply changing the bound style such as:

   $scope.gridOptions.styles = flexGrid.UIUtils.getThemebyId("new theme here").styles;

But this does not work.  The grid stays the same.  Can you tell me how to apply a new style after the grid is already rendered?  An example would be great.

Answer:

 

Unfortunately, there is no quick way to re paint the grid with new theme. 

 

If you look at our demo: http://www.htmltreegrid.com/demo/prod_jq_treegrid.html?example=Simple 

 

And click on the themes tab, you can switch themes. Below is the function we call once you switch themes. But this function actually destroys and re-creates the grid. This is the only certain way to definitively apply all style values, destroy internal cached information etc. 

 

 

myCompanyNameSpace.loadTheme=function(index){

    var theme=flexiciousNmsp.themes[index];

    if(!flexiciousNmsp.StyleDefaults._defaults){

        flexiciousNmsp.StyleDefaults._defaults={};

        flexiciousNmsp.UIUtils.mergeObjects(flexiciousNmsp.StyleDefaults._defaults,flexiciousNmsp.StyleDefaults.defaults);

    }

    var newStyles = {};

    flexiciousNmsp.UIUtils.mergeObjects(newStyles,flexiciousNmsp.StyleDefaults._defaults);

    flexiciousNmsp.UIUtils.mergeObjects(newStyles,theme.styles);

    flexiciousNmsp.UIUtils.mergeObjects(flexiciousNmsp.StyleDefaults.defaults,newStyles);

    myCompanyNameSpace.gotoTab(0);

};

 

 

Goto tab eventually runs the following code, but you might be able call grid.rebuild():

 

if (grid && grid.domElement && grid.domElement.parentNode){

        var domParent = grid.domElement.parentNode;

        var domElement = grid.domElement;

        grid.kill();

        domElement.innerHTML="";

        domElement.style.width="99%";

        domElement.style.height="99%";

        flexiciousNmsp.UIUtils.addChild(domParent,domElement);//because kill removes from dom.

    }

    grid = new flexiciousNmsp.FlexDataGrid(document.getElementById("gridContainer"),

        {

            dataProvider:dp,

            configuration:myCompanyNameSpace.SAMPLE_CONFIGS[config],

            styles:styles

        });

 

==============================

 

We have a grid with row background color:

myCompanyNameSpace.getCellBackground = function (cell) {

            if (cell.level.isItemSelected(cell.rowInfo.data)){

                  return cell.getStyleValue("selectionColor");

            }

 

            if (cell.rowInfo.getData().SLS_MON_STAT == "R") {

return 0xFF0000;

}

 

return null;  // keep default background color for all "normal" rows

      }

 

 

What the above code should do is, every row where the attribute SLS_MON_STAT equals to “R” should have a red background color. All other rows should have standard background color.

This works as expected so far, but the problem is that all red rows stay now in red forever. The “normal” rows (those that are not red) get a lightblue background as a temporary highlighting when the mouse hovers over them, and when a row is selected by clicking on it, it gets a darker blue background highlighting. But this highlighting does not work on the red rows.

 

How can I achieve that the highlighting works on all rows, even on those rows that are not in “default” background color?

 

 

 Answer:

In your getBackgroundFunction

 

Just add this condition:

 

 

if( grid.currentCell.rowInfo == cell.rowInfo){
         //this means cell is the same row that the mouse is over.
          return cell.getRolloverColor();

 

}


How to add custom interactive html from a labelFunction

clock March 16, 2016 18:47 by author htmltreegrid

Recently, we had a customer asking for a example of how to invoke custom logic from the code generated by a labelFunction.

for those of you who do not know what labelFunction is, it is a excellent mechanism to generate custom HTML for each cell. 

For more details, please refer:http://htmltreegrid.com/newdocs/html/Flexicious%20HTMLTreeGrid.html?ConfigurationOptionsInteractiveH.html 

 

In this example, we will see how you can get the labelFunction to return HTML with a call back function that gets you information about 

which cell the user clicked on. Note that the key is to pass in 'this' from the label functions output html, and navigate to the container cell.

The container cell can then give you a hook into the row, the data, and the cell.

 

custom-logic-labelfunction.html (3.90 kb)



How to add a custom tooltip to HTML TreeGrid DataGrid

clock February 28, 2016 06:25 by author htmltreegrid

Recently, we had a customer asking for some help implementing a tooltip. Out of the box, we provide an API that you can listen to. Using this API, you can plug in any custom tooltip implementation. 

In this example, we are going to use the jQuery tooltip component. Once implemented, this will look like the below screenshot:

 

And below is the sample code:

 

grid-cell-tooltip.html (20.50 kb)



How to highlight just a particular column in bold on selection

clock February 22, 2016 03:52 by author htmltreegrid

Recently had a question for a customer:

Would you have an example in your demo samples on your site to show how to set a specific row cell data to bold when the row is selected. I have a column called Product Id.

On row selection, the row has been highlighted but the user says they still want the product id set to bold so they can see that it is selected. I know the row is highlighted but it seems

 

 

It is not enough for them.  They want the product id in that selected row set to bold. 

 

What we currently do, is we attach the "Selected" style to each cell that is selected in the grid. This highlights the row in bold. But in this case we just want to highlight a single column in bold. 

So what we need to do, is to remove that style that highlights everything in bold.

We do this by

/* grid selected column styles reset. */
   
  .flexiciousGrid .selectedCell label{
  font-weight: normal !important;
  }

And then we assocaite a style with that column:

.flexiciousGrid .selectedCell .nameColumn{
  font-weight: bold !important;
  }
And finally, the column needs the nameColumn stytle
var customBoldStyleFunction = function(data, col){
  return "<span class='nameColumn'>"+data[col.getDataField()]+"</span>";
  };
   

Full example below:

 



grid-selected-column-bold-text.html (18.87 kb)