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)



How to refresh only a node within the HTML TreeGrid DataGrid

clock February 18, 2016 18:37 by author htmltreegrid

 

 

Question : Currently, I am using Treegrid in full lazy load, when I clicked a parent node it displays all the child nodes. Now my question is there any way with which I can refresh the opened level ? I want to reload the child again from server.. but for only one parent.

Answer:

Basically, the approach is very similar to what you would do when you loaded the children the first time. 

Lets look at some sample code:

First, lets add the button:

+  <div class="toolbar">  <button onclick="onRefreshClick()">Refresh Children of First Parent</button>

+</div>

On Refresh, we will just reload the first child:

+         function refreshChildren(parent, level){   if(!parent || !level)

+                return;

+            $.ajax({

+                url : GridConFig.ApiCallBaseUrl,

+                data : {name : "child_data", parent_id : parent.id},

+                type : "GET",

+                success : function(res){

+                    var response = JSON.parse(res);

+                    if(response.success){

+                        level.grid.setChildData(parent, response.data, level);

+                    } else {

+                        alert(response.message);

+                    }

+                }

+            });

+        }

+

+        function onRefreshClick(){

+            var grid = document.getElementById("grid-container").component;

+            if(!grid || !grid.getDataProvider())

+                return;

+            refreshChildren(grid.getDataProvider()[0], grid.getColumnLevel())

         }

 

 

 

 

 



Focus in on TextInput on edit

clock February 4, 2016 07:44 by author htmltreegrid

Recently a customer asked a question that helps demonsrate a couple of concepts

Basically what they wanted to do was to highlight the entire cell when starting an edit session. The default behavior of this functionality is that when you start an edit session, it will focus at the end of the text box. Assumption is that you want to continue to add to the textbox, But in this case, since the client wanted customizaiton of this functionality, there are multiple ways to do it. Although ideally you would do something like this in itemEditBegin event handler, we wanted to demonstrate another nifty way of customizing the stock behavior. Lets look at the code:

flexiciousNmsp.FlexDataGridContainerBase.prototype.stockBeginEdit = flexiciousNmsp.FlexDataGridContainerBase.prototype.beginEdit;
flexiciousNmsp.FlexDataGridContainerBase.prototype.beginEdit = function(cell){
    this.stockBeginEdit(cell);
    if(this.getEditor().implementsOrExtends("TextInput")){
        var txt=this.getEditor().getText();
        if(txt.length>0)
            this.getEditor().setSelection(0,txt.length);
    }

};

So what we did here is interesting:
WE took the stock beginEdit function, and essentiall renamed it stockBeginEdit. 
Then we made a new beginEdit function, where we dutifully call the stockBeginEdit
And then finally, we added our logic to beginEdit to highlight the entire text of the cell.

What we did here was nothing extra ordinary - we just leveraged the 
tremendous power of JavaScript - the ability redefine functional behavior at runtime. 


React DataGrid - initializing HTMLTreeGrid in componentDidMount of a React Component

clock February 1, 2016 04:31 by author htmltreegrid

Update 01/2016: We now have a PURE REACT DataGrid component (built completely in react) http://www.reactdatagrid.com/

 

So of late, a lot of you have been asking for integration with the excellent React Framework. As most of you are aware, we already integrate with AngularJS as we talked about in this blog post : http://blog.htmltreegrid.com/post/Angular-JS-Support.aspx

Well, React is now gaining momentum, and some would argue is on track to bypass angular in terms of popularity. We spent some time trying to understand and look at how best to integrate with react, and there are basicaly 2 options:

1) Just drop a div in a react component, and in componentDidMount, call the constructor of the FlexDataGrid. Here is the crux of this code:

var FlexDataGridBasic = React.createClass({
componentWillMount: function() {
this.grid = new flexiciousNmsp.FlexDataGrid();
},
componentDidMount: function() {
this.grid.setDomElement(this.refs.gridContainer);
},
componentDidUnMount: function() {
this.grid.kill();
},
render: function() {
return (
<div ref="gridContainer" className="flexiciousGrid" style={this.props.divStyle}></div>
);
}
});
And then in your main app
var MyScreen = React.createClass({
onCreationComplete : function(evt){
var grid = evt.currentTarget;
console.log('This message is sent from a callback')
},
onItemClick : function(evt){
var grid = evt.currentTarget;
alert('You clicked' + grid.getSelectedIndex());
},
render: function() {
var divStyle={width:'100%',height:'100%'};

return (

<FlexDataGridBasic ref="secondGrid" divStyle={divStyle}>
</FlexDataGridBasic>

);
},
componentDidMount : function() {

this.refs.secondGrid.grid.delegate=this;
this.refs.secondGrid.grid.buildFromXml('<grid forcePagerRow="true" enableFilters="true"  creationComplete="onCreationComplete" itemClick="onItemClick" enableEagerDraw="true" ><columns>' + '<column headerText="Col1" dataField="col1"/><column headerText="Col2" dataField="col2"/></columns></grid>');
    }
});
ReactDOM.render(
<MyScreen/>,
document.getElementById('content')
);

The advantage of this approach is that you can reuse all your XML configuration as is 
- and the delegate is your screen for all the callbacks. 

Now, the other approach is more React centric. Here, we define the markup of the grid as "React Markup"
<FlexDataGrid ref="firstGrid" forcePagerRow="true" enableFilters="true" creationComplete={this.onCreationComplete} 
     itemClick={this.onItemClick} enableEagerDraw="true" divStyle={divStyle}>
    <FlexDataGridColumnLevel>
<FlexDataGridColumn headerText="Col1" dataField="col1"/>
<FlexDataGridColumn headerText="Col2" dataField="col2"/>
</FlexDataGridColumnLevel>
</FlexDataGrid>
What this does is that it makes the entire markup bindable. It has the added advantage of being more "Reacty". 
Which one you choose is upto you - As always, this is a fairly newly added feature, and 
we are looking for feedback on it, so please help us and submit your feedback!
One more thing - you will need the latest build to make this work, so please request one!
Below is the file that demonsrates both these approaches:

react.html (13.85 kb)



AngularJS DataGrid Component - Markup structure for Angular DataGrid

clock January 31, 2016 00:40 by author htmltreegrid

If you have looked at our demo page, you already know that HTMLTreeGrid is arguably among the most powerful datagrid options available for JavaScript SPA developers. With our integration with Angular, we expose the power of our product to developers of Angular apps in a way that feels natural. 

Angular JS is one of the most widely used framework among our customer base. React is catching up fast, and with Angular 2 being such a major rewrite, things are moving very fast in this arena. We are also working on a React component that wraps the HTMLTreeGrid, but that is a subject for another blog post. 

Today, we want to talk about our offering specifically as it relates to angular 1.x. 

One of the most powerful features of Angular is the ability to define all markup in the HTML (this becomes your 'view' in MVC). Almost all other third party components that integrate with angular do it in a way that defeats the purpose of Angular's elegance.

For example, you will see them have a directive like this (Note that there is a ton of JavaScript code JUST to do the configuration of the grid - this makes it a lot harder to understand the HTML markup and how it relates to the actual grid structure):

 

<!--THIS PART GOES SOMEWHERE BURIED IN YOUR VIEW HIERARCY-->
<div ng-app="app" ng-controller="MyCtrl">
<div third-party--grid-component component-options="componentOptions" />
</div>
<!--THIS PART GOES SOMEWHERE BURIED IN YOUR SCRIPTS-->
<script>
angular.module("app", [ "thirdPartyDirective" ]).controller("MyCtrl", function($scope) {
$scope.componentOptions = {
gridOption1 : "val1",
gridOption2 : "val2",
gridOption3 : "val3",
columns : [
{
columnOption1 : "val1",
columnOption2 : "val2",
columnOption3 : "val3",
},
{
columnOption1 : "val1",
columnOption2 : "val2",
columnOption3 : "val3",
}
]
};
});
</script>

Now contrast this with our Angular Datagrid declaration
<html>
<body> ..rest of the html
<div id="gridContainer" fd-grid="" ng-model="gridOptions" style="height: 725px;width: 100%;"...>
<level xirow-Height="49">
<columns>
<column xidata-Field="id" xiheader-Text="ID" xicolumn-Width-Mode="fixed" xiwidth="150" />
            <column xidata-Field="City Name" xiheader-Text="City Name" />
        </columns>
</level>
</div>
... rest of the html
Do you see the difference? Our Angular markup is clean, self contained, and requires very little JavaScript -
everything is loaded straight from the view which makes Clear separation of presentation and logic possible.


Another nice thing about our product is we hate to 'reinvent the wheel'. 
We rely on well established frameworks, plugins, and libraries that our customers are already using. 
For example, all of our UI is built using either jQuery UI, EXT, or DOJO 
in a plugin mechansim - (which allowed us to recently and quite easily add integration with Bootstrap).

If you like what you see, feel free to check out a few examples that use our AngularJS integration directive : 
http://blog.htmltreegrid.com/post/Angular-JS-Support.aspx