How can I force ng-click to take precedence over an ng-blur event?
Solution 1
Instead of ng-click
, use ng-mousedown
. Mousedown events get fired before blur events.
However, the handled mousedown might un-focus your field without the blur event being fired. If you then click outside the box, the blur event won't be fired (because the field is already blurred), so after setting focus, you might need to re-focus the field manually - see How to set focus on input field?
Note that by using this approach, the button can also be triggered using right-click (thanks Alexandros Vellis!) as you can see in this official example.
Solution 2
Don't use ng-blur
then, bind the $document
with click
event to stop edit mode. And remember to unbind the event when the scope is destroyed.
Solution 3
If you want to run click event functionality before ng-blur
than write your functionality in ng-mousedown
event instead ng-click
.
tidelipop
I work as a professional webdeveloper, mainly e-commerce sites.
Updated on September 11, 2020Comments
-
tidelipop almost 4 years
When I click the save button it triggers an ng-blur event, how can I make the buttons ng-click event to trigger instead? I still want the ng-blur event to trigger if I click outsida the button or input field.
http://jsfiddle.net/tidelipop/wyjdT/
angular.module('MyApp', []) .filter("placeholder", function(){ return function (text, length, end) { //console.log(typeof text, text, length); if(typeof text === 'undefined' || text == ''){ text = 'Click to edit...'; } return text; }; }) .directive("inlineEdit", function($compile, $q){ return { restrict: "A", replace: true, template: function(tElement, tAttrs){ var modelStr = tAttrs.inlineEdit, optionsStr = tAttrs.options, modelXtra = '', editElStr = ''; if(tAttrs.type === 'selectbox'){ modelXtra = '.value'; editElStr = '<select ng-show="editMode" ng-blur="endEdit(\''+modelStr+'\')" ng-model="'+modelStr+'" ng-options="a.value for a in '+optionsStr+'"></select>'; }else if(tAttrs.type === 'textarea'){ editElStr = '<textarea ng-show="editMode" ng-blur="endEdit(\''+modelStr+'\')" ng-model="'+modelStr+'"></textarea>'; }else{ editElStr = '<input type="text" ng-show="editMode" ng-blur="endEdit(\''+modelStr+'\')" ng-model="'+modelStr+'" />'; } return '<div class="body">'+ '<span ng-hide="editMode" ng-click="startEdit(\''+modelStr+'\', \''+optionsStr+'\')" ng-bind="'+modelStr+modelXtra+' | placeholder"></span>'+ editElStr+'<button ng-show="editMode" ng-click="save()">save</button>'+ '</div>'; }, scope: true, controller: function($scope){ $scope.editMode = false; $scope.save = function(){ console.log("Saving..."); $scope.editMode = false; }; $scope.startEdit = function(modelStr, optionsStr){ console.log("Start edit mode..."); // Store original value, to be restored if not saving... $scope.origValue = $scope.$eval(modelStr); // If selectbox and no initial value, do init to first option if(typeof $scope.origValue === 'object' && typeof $scope.origValue.value !== 'string'){ $scope.$eval(modelStr+'='+optionsStr+'[0]'); } // Turn on edit mode $scope.editMode = true; }; $scope.endEdit = function(modelStr){ console.log("End edit mode..."); // Restore original value $scope.$eval(modelStr+'=origValue'); // Turn off edit mode $scope.editMode = false; }; } } }) .controller("UserAdminCtrl", function($scope){ $scope.options = {}; $scope.options.cars = [ { "key": 0, "value": "Audi" }, { "key": 1, "value": "BMW" }, { "key": 2, "value": "Volvo" } ]; $scope.data_copy = { user: { user_id: 'sevaxahe', comment: '', my_car: {} } }; });
-
tidelipop almost 11 yearsDoesn't work so well, since it triggers when I click inside the selectbox or when I make a selection. What do you mean "unbind the event when the scope is destroyed". When is the scope destroyed and how do I do that?
-
6220119 almost 11 yearsIt can be destroyed by several ways, e.g. on data changed of ng-repeat, switching the ng-view, ...
-
Uli Köhler over 9 years@WylieKulicuu Happy to help ;-) It indeed took me half a week to figure out the solution
-
Alexandros V almost 9 years@UliKöhler I liked this answer. However make a note that when doing this, the <button> elements can also be triggered with a right mouse click, which might not be desired...
-
Uli Köhler almost 9 years@AlexandrosVellis Very good point indeed! I have added this to the answer. You can actually see this in the official
ng-mousedown
example. Are you aware of any method of solving this? -
Uli Köhler over 8 years@TheProgrammer Thanks, I will definitely do ;-)
-
Kimball Robinson over 8 yearsI was having a problem with a
<a ng-click="....">
that wasn't firing until the second time I clicked it. This turned out to be the solution. Thanks!! -
RaphaMex over 6 yearsGreat solution! I was considering using $timeout inside ng-blur to let time for my ng-click to trigger... Saved my day :-)