Piotrek
Piotrek

Reputation: 11221

How to call ng-click before ng-blur?

I've created a text input with some suggestions appearing while typing (just like on Google - you are writing something and it suggests you some text).

<input id="smartBar" ng-focus="showSuggestions=true" ng-blur="showSuggestions=false" ng-model="smartBar" ng-keydown="smartBarKeyDown($event)" focus-on="smartBar" />
                <table class="suggestionList" ng-show="showSuggestions">
                    <tr ng-repeat="sg in suggestions" ng-class="{highlighedSuggestion: $index == highlightedSuggestion}" ng-click="suggestionClicked($index)">
                        <td ng-repeat="nt in sg.NoteTags" style="padding: 0rem 1rem">
                            {{nt.Tag.Name}}
                        </td>
                    </tr>
                </table>

I want to add possibility to click on one of "suggestions" (there is ng-click attribute in < TR> html attribute). Unfortunately, ng-blur seems to work earlier than ng-click, so when I click on one of options, input loses focus and suggestionList becomes invisible before click is detected.

How can I detect click before hiding suggestionList?

Upvotes: 4

Views: 2488

Answers (3)

Wojtek Majerski
Wojtek Majerski

Reputation: 3637

Had exactly the same problem while developing my own autocomplete dropdown list. Both $timeout and ng-mousedown solutions were too dirty for me and had negative UX side-effects. This is what I figured out eventually:

var suppressInputFocusedChange = false;

$scope.onBlur = function() {
    if(suppressInputFocusedChange === true) {
        suppressInputFocusedChange = false;
        return false;
    }
    $scope.showSuggestions = false;
};

$scope.onFocus = function() {
    $scope.showSuggestions = true;
};

$scope.suggestionMouseDown = function() {
    suppressInputFocusedChange = true;
};

$scope.suggestionClicked = function() {
    $scope.showSuggestions = false;
};

So basically, when you start to click on the item (ng-mousedown) you set the suppressInputFocusedChange flag to true. When this flag is up 'onBlur' method will do nothing and the list will be hidden by the suggestionClicked method.

Upvotes: 1

georgeawg
georgeawg

Reputation: 48968

One of your options is use a $timeout to delay the removal of the suggestion list, and $cancel the timeout from the click event.

var suggestionTimeout = $timeout(angular.noop);

function setSuggestionFalse = function() {
    vm.showSuggestions = false;
 };

vm.onSmartBarBlur = function () {
    //delay the removal
    suggestionTimeout = $timeout(setSuggestionFalse, 50);
};

vm.onSuggestionClick = function () {
    //cancel the removal
    $timeout.cancel(suggestionTimeout);
    //show suggestion
};

For more information in $timeout see the AngularJS $timeout API Reference.

Upvotes: 0

Tarun Dugar
Tarun Dugar

Reputation: 8971

You cannot. However, you can use ngMousedown instead of ngClick to achieve the desired functionality:

HTML:

ng-mousedown="suggestionClicked($index, $event)

JS:

$scope.suggestionClicked = function(index, evt) {
    //detect left click
    if(evt.which === 1) {
        //your code
    }
}

Upvotes: 2

Related Questions