Ng-grid: Export Feature

   From a front-end standpoint it's easy to use ng-grid since a lot of the variables already exist. What I did in my implementation was leverage as much of ng-grid as possible before creating my own functions. Displayed fields in the grid that are checked by default are also checked in the export dialog. This feature was written up to handle hidden fields in the grid as well and gives the user the option to select or deselect all the available fields to export. However this example assumes that "name" field is a key on the server side and if passed to the server could give you whatever is in the database. So if you were looking to attach this to a more meaningful system you would pass just the key and fields to the server in order to get your results.
 
Solution:
<!--Html part-->
<button type="button" class="btn btn-success pull-right" data-toggle="modal" data-target="#exportModal">Export to Data</button>
<div class="modal fade" id="exportModal" tabindex="-1" role="dialog" aria-labelledby="exportModalLabel" aria-hidden="true">
 <div class="modal-dialog">
  <div class="modal-content">
   <div class="modal-header">
    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
    <h4 class="modal-title">Please select your fields to export.</h4>
   </div>
   <div class="modal-body">
    <ul>
     <li class="ng-scope">
      <div id="allfields" class="checkbox"><input type="checkbox" ng-click="allNeedsClicked()" ng-checked="allNeedsMet()"/>
       <label for="allfields" >All Fields</label>
      </div>
     </li>                                    
     <ul>
      <li ng-repeat="field in fieldsExport">                        
       <div class="checkbox"><input id="{{$index}}" type="checkbox" ng-model="field.visible" />
        <label for="{{$index}}">{{field.field}}</label>
       </div>
      </li>
     </ul>
    </ul>
   </div><br />
   <div class="modal-footer">                            
    <button ng-show="gridOptions.selectedItems.length  > 0" onclick="exportClick()" class="btn btn-primary">Export Selected</button>
    <button onclick="exportClick()" class="btn btn-primary">Export All</button>
   </div>
  </div>
 </div>
</div>

//*** Export Stuff... ***//
$scope.fieldsExport = $scope.gridOptions.columnDefs;

$scope.onCompleteTodo = function (todo) {
 $scope.fieldsExport[todo].visible = !$scope.fieldsExport[todo].visible;
};
exportClick = function (flag) {        
 var List = "";
 for (var i = 0; i < $scope.fieldsExport.length; i++) {            
  if ($scope.fieldsExport[i].visible)
   List += ($scope.fieldsExport[i].field + ',');            
 }        
 $('#exportModal').modal('hide');
  if(!flag)  {
  for (var t=0; t< $scope.gridOptions.selectedItems.length; t++){
    //Assume name is unqiue and can be used as the key on the server.
    List += ($scope.gridOptions.selectedItems[t].name + ',');
  }
  }
   window.open("data:text/html," + encodeURIComponent(List),
       "_blank", "width=200,height=100");
    
};

$scope.allNeedsClicked = function () {
 var newValue = !$scope.allNeedsMet();        
 for (var i = 0; i < $scope.fieldsExport.length; i++) {
  $scope.fieldsExport[i].visible = newValue;
 }
};

$scope.allNeedsMet = function () {
 var needsMet = [];
 for (var i = 0; i < $scope.fieldsExport.length; i++) {
  if ($scope.fieldsExport[i].visible === true)
   needsMet.push(true);
 }
 return (needsMet.length === $scope.fieldsExport.length);
};

Example: http://plnkr.co/edit/KHqwzjeiLHZ9MINMpaUW?p=preview

Notes - (Not in the Example)
    There is some logic that I wrote but did not include in the example because of how I solved the issue and didn't like my approach with it but I will explain it here. When a user has selected fields to be displayed in the grid, this updates the export dialog and whether fields appear checked. However it does not work the other way around, where the user has checked in the export dialog This is because if the users was in the export dialog and checking or unchecked boxes if would in the background (just in the user's vision) update the grid. Which in my opinion would not be a good user experience since it would draw the user's attention outside a dialog. Web dialogues should always be the focus for a users attention. Rather than redefine the fields in the grid, I can simply hooked into the grid's columnDefs and update on ng-grid's ng-repeat for the columns using ng-change inside ng-grid templates. So pretty much are coded it but I would recommend using a watch on the variable or creating a directive like the example listed below.

Resources
Note that selectItems is an array not an int: Getting select rows from ng-grid?
javascript - Open a new tab/window and write something to it? - Exporting Example
angularjs - how to hide/show ng-grid column externally? - Another approach using directives instead.
I'm aware of this solution as well, but it's a lot of code in the frontend when I need to talk back to the server.

Popular posts from this blog

Nginx Best Practices Extended

Installing Windows on Acer chromebook 15 cb3-532

Entity Framework: ToListAynsc & WhereAsync