10

VERSION:

I am using Angular ui-grid version 3.0.0-RC.18 (http://ui-grid.info/).

PROBLEM

I want to implement a double-click event in an ui-grid table. In particular, I want to open a modal pop-up when double-clicking at a row.

I tried to use a ng-dblclick directive inside the rowTemplate definition as is suggested at https://github.com/angular-ui/ng-grid/issues/2228 , but 'dblclick' event is never fired.

Nevertheless, I found a solution, but using a directive created by my own. Can I do it better, without creating a directive?

Any comment would be appreciated.

CODE:

My code at the Controller is as follows:

$scope.onDblClick = function(row) {
    var url = '//google.com';
    $window.open(url, "_blank", "height=600,width=800,toolbar=no,location=no,menubar=no,titlebar=no");
}

// Define the New Conflicts Simulation GRID behavior
$scope.myGridOptions = {
    showFooter: false,
    enableSorting: true,
    multiSelect: false,
    enableFiltering: true,     
    enableRowSelection: true, 
    enableSelectAll: false,
    enableRowHeaderSelection: false,  
    enableGridMenu: true,
    noUnselect: true,
    onRegisterApi: function (gridApi){
        $scope.gridApi = gridApi;
    },
    rowTemplate: "<div ng-dblclick=\"onDblClick(row)\" ng-repeat=\"(colRenderIndex, col) in colContainer.renderedColumns track by col.colDef.name\" class=\"ui-grid-cell\" ng-class=\"{ 'ui-grid-row-header-cell': col.isRowHeader }\" ui-grid-cell dbl-click-row></div>"            

}

(Where dbl-click-row indicates I am using the dblClickRow directive)

My code at the View is as follows:

<div id="myGrid" ui-grid="myGridOptions" ui-grid-selection ui-grid-resize-columns class="gridTable" ></div>

My code at the Directive is as follows:

var angularStartDirectives = angular.module('angularStart.directives', []);     

angularStartDirectives.directive('dblClickRow', ['$compile', '$parse',  function($compile, $parse) {
  return {
    priority : -190, // run after default uiGridCell directive
    restrict : 'A',
    scope : false,

    compile: function($element, attr) {

        // Get the function at ng-dblclick for ui-grid
        var fn = $parse(attr['ngDblclick'], /* interceptorFn */ null, /* expensiveChecks */ true);

        return function ngEventHandler(scope, element) {

            element.on('dblclick', function(event) {

              var callback = function() {

                if ($scope.gridApi.grid.selection.lastSelectedRow)
                {
                    fn($scope, {$event:event, row: $scope.gridApi.grid.selection.lastSelectedRow.entity });
                }
              };

              $scope.$apply(callback);

            }
        )};

    }

    };
} ]);

3 Answers 3

17

Well, my question was answered at Github:

https://github.com/angular-ui/ng-grid/issues/2228#issuecomment-71912850

My mistake was not to use external-scopes, and try to solve the problem with ng-dblclick only.

The code should be like this:

At the Controller:

$scope.gridHandlers = { 

    onDblClick : function(row) {
        var url = '//google.com';
        $window.open(url, "_blank", "height=600,width=800,toolbar=no,location=no,menubar=no,titlebar=no");
   }
}

$scope.myGridOptions = {
    showFooter: false,
    enableSorting: true,
    multiSelect: false,
    enableFiltering: true,     
    enableRowSelection: true, 
    enableSelectAll: false,
    enableRowHeaderSelection: false,  
    enableGridMenu: true,
    noUnselect: true,
    onRegisterApi: function (gridApi){
        $scope.gridApi = gridApi;
    },
    rowTemplate: "<div ng-dblclick=\"getExternalScopes().onDblClick(row)\" ng-repeat=\"(colRenderIndex, col) in colContainer.renderedColumns track by col.colDef.name\" class=\"ui-grid-cell\" ng-class=\"{ 'ui-grid-row-header-cell': col.isRowHeader }\" ui-grid-cell ></div>"            

}

At the View:

<div id="myGrid" ui-grid="myGridOptions" ui-grid-selection ui-grid-resize-columns class="gridTable" external-scopes="gridHandlers"></div>

Update for ui-grid v3.0.0-rc.21:

Considering that externalScopes is no longer supported, and now appScopeProvider rules.

In the view:

<div id="myGrid" ui-grid="myGridOptions" ui-grid-selection ui-grid-resize-columns class="gridTable" ></div>

In the controller:

$scope.myGridOptions = {
    showFooter: false,
    enableSorting: true,
    multiSelect: false,
    enableFiltering: true,     
    enableRowSelection: true, 
    enableSelectAll: false,
    enableRowHeaderSelection: false,  
    enableGridMenu: true,
    noUnselect: true,
    onRegisterApi: function (gridApi){
       $scope.gridApi = gridApi;
    },
    appScopeProvider: { 
        onDblClick : function(row) {
           var url = '//google.com';
           $window.open(url, "_blank", "height=600,width=800,toolbar=no,location=no,menubar=no,titlebar=no");
         }
    },
    rowTemplate: "<div ng-dblclick=\"grid.appScope.onDblClick(row)\" ng-repeat=\"(colRenderIndex, col) in colContainer.renderedColumns track by col.colDef.name\" class=\"ui-grid-cell\" ng-class=\"{ 'ui-grid-row-header-cell': col.isRowHeader }\" ui-grid-cell ></div>"
}

Here is my example at Plnkr using a modal popup (done with angular-ui-bootstrap):

http://plnkr.co/edit/cq7s9lKn90xTVgNxIC6b?p=preview

Note that if you use a newer version of ui-bootstrap, you will need to rename $modal in the above plunkr to $uibModal.

Sign up to request clarification or add additional context in comments.

5 Comments

I found converting the rowTemplate from ng-grid to ui-grid to be a problem. This finally worked for me once I realized I had a typo on the function name.
I've been trying this for hours and I can't get it to work. One part of the challenge is that I don't know what's part of the solution and what's irrelevant. Any chance you could remove some of the irrelevant parts?
I actually ended up figuring it out myself. Details in this answer.
Is it possible to edit those values in external scope ?
appScopeProvider row clicks working well but another single click button in cellTemplate(in a column) is not working now. Any possible solution?
2

I've used Aquiles solution and reduced scopes just to appSCope, see here.

I've rewrite code to showInfo becomes to $scope:

$scope.showInfo = function(row) {
    var modalInstance = $modal.open({
      controller: 'InfoController',
      templateUrl: 'ngTemplate/infoPopup.html',
      resolve: {
        selectedRow: function () {                    
            return row.entity;
        }
      }
   });

   modalInstance.result.then(function (selectedItem) {
     $log.log('modal selected Row: ' + selectedItem);
   }, function () {
     $log.info('Modal dismissed at: ' + new Date());
  });
}

At gridOptions just used appScope:

$scope.gridOptions = {

   showFooter: true,
   enableSorting: true,
   multiSelect: false,
   enableFiltering: true,     
   enableRowSelection: true, 
   enableSelectAll: false,
   enableRowHeaderSelection: false,
   selectionRowHeaderWidth: 35,  
   noUnselect: true,
   enableGridMenu: true,
   columnDefs: [{displayName:'Name',field:'name'},{displayName:'Gender',field:'gender'},{displayName:'Company',field:'company'}],
   rowTemplate: "<div ng-dblclick=\"grid.appScope.showInfo(row)\" ng-repeat=\"(colRenderIndex, col) in colContainer.renderedColumns track by col.colDef.name\" class=\"ui-grid-cell\" ng-class=\"{ 'ui-grid-row-header-cell': col.isRowHeader }\" ui-grid-cell></div>"
};

Too, I added columnDefs to show that rowTemplate don't interfere with grid rendering.

Comments

0

The solution with custom rowTemplate works fine. I've found a more elegant solution which adds the event to the 'ui-grid/ui-grid-row' template:

rowTemplate : $templateCache.get('ui-grid/ui-grid-row').replace("<div ", "<div ng-dblclick=\"grid.appScope.onDblClick(row, $event)\" "),

The double click event handler would be something like this:

$scope.onRowDblClick = function (row) {
    if (row && row.entity) {
        //insert your custom code
    }
};

You'll have to add the dependency to $templateCache in your controller.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.