angular-ui / ui-grid

UI Grid: an Angular Data Grid
http://ui-grid.info
MIT License
5.39k stars 2.47k forks source link

UI-Bootstrap typeahead doesn't work in editable grid #3463

Closed mattsharpe closed 6 years ago

mattsharpe commented 9 years ago

Hi guys, I'm using the ui-bootstrap inside my grid and hitting some issues, I've read through #3115 but the plunker in the solution doesn't seem right. http://plnkr.co/edit/ai91kJMiApXktc4vM4mt?p=preview Try typing 'New' in the first row then hitting enter to select 'New Hampshire', nothing happens.

I'm seeing the same behaviour in my app, no keyboard select or mouse select will work to choose a drop down item. Any ideas?

trytocatchme commented 9 years ago

Hi, call to 'data-typeahead-on-select="typeaheadSelected(row.entity, $item)" ' also doesn't work. I think it is related to the autocomplete.

PaulL1 commented 9 years ago

I'm not sure that's currently supported, I think someone would have to dig through it. No doubt we're trapping the enter key and using it for something else, so you might need to dig through the code and work out where. At a guess I'd say the edit feature is trapping it.

unkn0wn-kgb commented 9 years ago

Using this cell template with appScope still typeahead very consufed

<form name="inputForm"> <div class="typeaheadcontainer"><input type="text" ' +
            'class="typeaheadcontrol" ' +
            'ui-grid-editor ' +
            'data-ng-model="grid.appScope.mymodel" ' +
            'data-typeahead="name as state.name for state in grid.appScope.states | filter:$viewValue | limitTo:8" ' +
            'data-ng-required="true" ' +
            'data-typeahead-editable ="false"' +
            //'data-typeahead-on-select="grid.appScope.typeaheadSelected($item, $model, $label)" ' +
            '/></div></form>

I have tracked it down inside typeahead ui-bootstrap-tpls.js

} else if (evt.which === 13 || evt.which === 9) {
          scope.$apply(function () {
            scope.select(scope.activeIdx);
          });

        }

Something is wrong with the scope and type ahead fails to call select and if I modify this to

ui-bootstrap-tpls.js

} else if (evt.which === 13 || evt.which === 9) {
          scope.select(scope.activeIdx);
         scope.$apply(function () {
            scope.select(scope.activeIdx);
          });

        }

then inside select it fails to workout selected text

model = parserResult.modelMapper(originalScope, locals);

So it seems grid.appScope is the issue.

Would be awesome to get typeahead working with ui-grid as I am currently looking for other options like jquery autocomplete and not looking forward for that.

willw-git commented 9 years ago

+1 I'm stuck on this too, and can't find a work-around; frankly it is beyond my DOM expertise.

unkn0wn-kgb commented 9 years ago

Yes that would be awesome to get typeahead working with ui-grid however I've started on jquery ui autocomplete integration and creating a custom directive for binding so far its going ok, much easier than getting typeahead to work properly without modifying the core. I hope one day this would get done with typeahead would even pay for this feature.

hydra1983 commented 9 years ago

+1

hydra1983 commented 9 years ago
scope.$apply(function () {
    scope.select(scope.activeIdx);
});

The inside "select" is not executed in my situation.

hydra1983 commented 9 years ago
scope.select(scope.activeIdx);
scope.$apply();

Putting the "select" outside $apply can have "enter" key working, but the mouse click takes no effect.

image

image

unkn0wn-kgb commented 9 years ago

Yeah same results here, that handsontable that you have mentioned does look promising, let me know how that goes

hydra1983 commented 9 years ago

The $apply funciton is "noop" when working with ui-grid together. That's the reason the inner line can not be executed I think.

screen shot 2015-06-07 at 17 18 15

It should be something like this,

screen shot 2015-06-07 at 17 23 50

hydra1983 commented 9 years ago

The "$apply" is "noop" only when lines below executed:

scope.$apply(function () {
    scope.select(scope.activeIdx);
});

Quite strange

hydra1983 commented 9 years ago

On "enter" "keydown", image

stopEdit is called and which will destroy the originalScope

image

So the $apply of scope in the lines below will be noop after originalScope is destroyed.

image

unkn0wn-kgb commented 9 years ago

So is it possible to write hack to overwrite endEdit?

hydra1983 commented 9 years ago

The event should be bubbled from the inner typeahead to the outer ui grid I think. But the actual direction is contrary. I'm looking for the cause. The solution should be, the keydown handler of typeahead is executed before the keydown handler of ui grid.

hydra1983 commented 9 years ago

image

image

Seems the event bind to the same element, and ui grid bind the event earlier than typeahead. Follow the rule First come and first out(See here), the event handler bind in ui grid will be executed firstly.

hydra1983 commented 9 years ago

The solution 2 here can resolve this problem. But need tests to make sure other functions are not affected.

image

hydra1983 commented 9 years ago

This is not the best solution I think. A better way should be capturing keydown event on typeahead popup and process the logic to change the model then propagate the event to ui-grid.

brick80 commented 9 years ago

not sure if this will help, but I had a similar problem with angular ui-grid edit with typeahead autocomplete.

i could not select values from the list with my mouse until I used

typeahead-select-on-blur="true"

wesleycho commented 9 years ago

I'm not sure what is the issue here - I was able to get it to work here.

unkn0wn-kgb commented 9 years ago

@wesleycho Issue is that model data does not gets bind. Try to bind object then see if that objects gets changed it won't. See my comments above. (grid.appScope.typeaheadSelected($item, $model, $label))

Not only that typeahead has to visually work but also it should be able to bind models appropriately. I hope this helps

wesleycho commented 9 years ago

Thanks for the info - I'm new to the project, and have a lot to catch up on before I can get things moving full swing (+ leading UI Bootstrap work), so I'll try to take a look when I can.

unkn0wn-kgb commented 9 years ago

@wesleycho no worries ;) Awesome news, good to see more people joining

wesleycho commented 9 years ago

@unkn0wn-kgb how about this?

unkn0wn-kgb commented 9 years ago

@wesleycho Have updated your example to illustrate problem have a look at Entity State http://plnkr.co/edit/ni8IzWyCWJ8vRYN3mR5X?p=preview

To see the problem try to select something from dropdown and see if entity.state model is actually set. Then see if gridOptions.data gets updated with new selected state

thefewminutes commented 8 years ago

+1

ghost commented 8 years ago

The same happens to me, only work with 'Enter' key, but if I try with Click, the model doesn't bind

Fr4ncx commented 8 years ago

any suggestion?

joebo commented 8 years ago

I worked around the issue with the click by creating my own directive and basically just copy/pasting from uiGridEditor and then commenting out this line...

app.directive('myUiGridEditor',

...

                //needed to comment out for typeahead
              $elm.on('blur', function (evt) {
                //$scope.stopEdit(evt);
              });
tellingson commented 8 years ago

The stopEdit event emits 'uiGridEventEndCellEdit'. If you send that yourself, the edit will end. Using the fiddler given earlier by @wesleycho, I was able to successfully hookup autocomplete, have it set the model on click/enter and then close the edit.

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

unkn0wn-kgb commented 8 years ago

@tellingson what would be cool if you could modify ui-grid itself and create pull request. ;)

tellingson commented 8 years ago

@unkn0wn-kgb While that would be cool, I'm not sure how I would fix the problem in ui-grid. And I would guess that it would be beyond my skill level * commitable time.

chedched commented 8 years ago

+1

wesleycho commented 8 years ago

Please do not add +1s to issues, they generate no useful signal.

chedched commented 8 years ago

Sorry @wesleycho. I took @tellingson 's solution and put in a directive that triggers uiGridEventEndCellEdit if one clicks outside the grid, otherwise the cells keep in edit mode infinitely: http://plnkr.co/edit/wsfddO7D8nC0aLzb0Z45?p=preview.

It's a pretty dirty workaround though and doesn't work with multiple grids on a page.

syedrehman commented 8 years ago

HI everyone.

I am working on angular UI grid, and using autocomplete view inside a cell . My requirement is if i change a autocompelte value in a cell. other cell value should get updated. Note: other cell value is id of autocomplete cell.

Thank you

smirciat commented 8 years ago

@chedched : I appreciate your dirty workaround since sometimes those are easier to follow than a more succinct solution! I wanted to be able to end the edit also when navigating around the grid. For example, typing an item not in the typeahead pulldown list, then navigating to the next cell over should stop the edit. I solved this by including $scope.$broadcast('uiGridEventEndCellEdit'); in the gridApi.cellNav.on.navigate event under the $scope.gridOptions.onRegisterApi function. http://plnkr.co/edit/8ES5L4tPpA80u8x4tZWq?p=preview

smirciat commented 8 years ago

@syedrehman you should be able to watch for gridApi.edit.on.afterCellEdit event under the $scope.gridOptions.onRegisterApi function like this:

scope.gridApi.edit.on.afterCellEdit(scope,function(rowEntity, colDef, newValue, oldValue){
  if (colDef.name==="Autocomplete Column Name") {
    rowEntity._id="new id value";
  }
});
smirciat commented 8 years ago

When a user navigates ui-grid, they get used to the default behavior of the tab key navigating horizontally. Using typeahead as described here intercepts the keypress event. An item needs to be selected or the edit otherwise cancelled before ui-grid gets keypress events once again. It seems like it should be possible to have the tab keypress event forwarded from typeahead back to ui-grid so that the user experience is closer to spreadsheet/Access. If anyone has advice on how to begin that, I would love to hear it.

smirciat commented 8 years ago

I am sooo close to my desired behavior here: http://plnkr.co/edit/4O3jjPStQ9caqTUqzoMg?p=preview . I have the cellNav.on.navigate broadcasting uiGridEventEndCellEdit to clear the dropdown on navigation, as well as triggering a 'select' on the input so that the user can single click the cell and begin typing. My last hiccup is that by adding ui-grid-editor to the input element, it allows the cellNav hotkeys to work still, which is what I want. The downside is that the user can not select with mouseclick, only with enter. the user click to select fires navigate before $scope.typeaheadSelected can run. My workaround is changing the behavior of ui-grid-editor so that on blur, it delays 50ms with $timeout before stop edit to allow $scope.typeaheadSelected to run first.

luposung commented 6 years ago

A solution with enableCellEditOnFocus = true. Plunker

faheemhameed commented 4 years ago

I am sooo close to my desired behavior here: http://plnkr.co/edit/4O3jjPStQ9caqTUqzoMg?p=preview . I have the cellNav.on.navigate broadcasting uiGridEventEndCellEdit to clear the dropdown on navigation, as well as triggering a 'select' on the input so that the user can single click the cell and begin typing. My last hiccup is that by adding ui-grid-editor to the input element, it allows the cellNav hotkeys to work still, which is what I want. The downside is that the user can not select with mouseclick, only with enter. the user click to select fires navigate before $scope.typeaheadSelected can run. My workaround is changing the behavior of ui-grid-editor so that on blur, it delays 50ms with $timeout before stop edit to allow $scope.typeaheadSelected to run first.

Thanks... Your solution worked for me. I had copied the ui-grid-editor directive and used directly in my solution with a different name. I have just added the $timeout and it seemed to work.


                $scope.stopEdit = function (evt) {
                    //adding this timeout because the mouseclick event of the typeahead was not firing early or the edit is stopped earlier than the click event
                    $timeout(function () {
                        if ($scope.inputForm && !$scope.inputForm.$valid) {
                            evt.stopPropagation();
                            $scope.$emit(uiGridEditConstants.events.CANCEL_CELL_EDIT);
                        } else {
                            $scope.$emit(uiGridEditConstants.events.END_CELL_EDIT);
                        }
                        $scope.deepEdit = false;

                    }, 300);
                };