Combining ng-grid and ui-select2: unable to select

2019-09-08 15:02发布

In the editableCellTemplate of an ng-grid, I wanted to use a more user-friendly dropdown, and I found ui-select2 to be a good one.

The thing is however, that any click on this component, when it is used inside the ng-grid, results in the cell juming back to non-editable mode.

This way I can't select another value using the mouse (I can using the arrows on my keyboard).

When I put the dropdown in the cellTemplate, it works, but it should also work in the *editable*CellTemplate.

Some code to see what I mean can be found here.

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

Does anyone know why that happens, and what could be done to work around it?

2条回答
不美不萌又怎样
2楼-- · 2019-09-08 15:28

I updated the plunker with the solution (last grid shown).

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

The idea is that you should 'talk to ng-grid' exactly like the other editablCellTemplates do. These 'rules' aren't well defined in the documentation, but they could be deduced by looking at ng-grid's source code for the ng-input directive.

Basically, your own component should respond to the ngGridEventStartCellEdit event by focusing your editor element, and the most important thing is: your component MUST emit the ngGridEventEndCellEdit event only when the cell loses focus (or when you want the editor to disappear, like maybe when pressing enter or something).

So for this specific case I created my own directive that adds the necessary behaviour to a ui-select2 element, but I imagine you could understand what you'd have to do for your own specific case.

So, as an example, here is my ui-select2 specific directive:

app.directive(
            'uiSelect2EditableCellTemplate', 
            [ 
                function() {
                    return {
                        restrict: "A",
                        link: function ( scope, elm, attrs ) {
                            //make sure the id is set, so we can focus the ui-select2 by ID later on (because its ID will be generated from our id if we have one)
                            elm.attr( "id", "input-" + scope.col.index +  "-" + scope.row.rowIndex );

                            elm.on( 'click', function( evt ) {
                                evt.stopPropagation();
                            } ); 

                            elm.on( 'mousedown', function( evt ) {
                                evt.stopPropagation();
                            } ); 

                            //select2 has its own blur event !
                            elm.on( 'select2-blur', 
                                        function ( event ) { 
                                            scope.$emit( 'ngGridEventEndCellEdit' );                                                
                                        } 
                            );

                            scope.$on( 'ngGridEventStartCellEdit', function () {
                                //Event is fired BEFORE the new elements are part of the DOM, so try to set the focus after a timeout
                                setTimeout( function () {
                                                $( "#s2id_" + elm[0].id ).select2( 'open' );
                                            }, 10 );
                            } );


                        }
                    };
                }
            ] 
);

and my own editableCellTemplate would have to look something like this:

$scope.cellTemplateDropdownUiSelect3 =
'<select ui-select2-editable-cell-template ui-select2 ng-model="COL_FIELD" style="width: 90%" >' +
            '<option ng-repeat="(fkid, fkrow) in fkvalues_country" value="{{fkid}}" ng-selected="COL_FIELD == fkid" >{{fkrow}} ({{fkid}})</option>' +
'</select>' ;

A little bit of 'official' information can be found here: https://github.com/angular-ui/ng-grid/blob/master/CHANGELOG.md#editing-cells

查看更多
做自己的国王
3楼-- · 2019-09-08 15:29

the template for datepicker

<input type="text" datepicker ng-model="COL_FIELD"/>

and the angular directive would look like this.

 app.directive('datepicker',

      function () {
          return {

              restrict: 'A',
              require: '?ngModel',
              scope: {},
              link: function (scope, element, attrs, ngModel) {

                  if (!ngModel) return;
                  var optionsObj = {};
                  optionsObj.dateFormat = 'dd/mm/yy';
                  optionsObj.onClose = function(){
                    scope.$emit( 'ngGridEventEndCellEdit' ); 
                  }


                  var updateModel = function (date) {
                                            scope.$apply(function () {
                                            ngModel.$setViewValue(date);
                                        });
                                };

                  optionsObj.onSelect = function (date, picker) {
                      updateModel(date);
                  };

                  ngModel.$render = function () {
                      element.datepicker('setDate', ngModel.$viewValue || '');
                  };

                scope.$on('ngGridEventStartCellEdit', function (obj) {
                    element.datepicker( "show" );  
                });

                scope.$on('ngGridEventStartCellEdit', function (obj) {
                    element.datepicker( "show" );  
                });
                element.datepicker(optionsObj);

              } 
          };
      });
查看更多
登录 后发表回答