I'm trying to create a dynamic text-field in AngularJS like I've seen on many websites. When you hover over the field an 'edit' button should appear and if you click the 'edit' button you can both change the value and the 'edit' changes to a 'save' button. If you click anywhere outside of the text-field the field discards any changes and returns to its initial state.
Looking at the markup below, the 'click-anywhere-but-here' directive (provided by another stack overflow user to another question) doesn't seem to be executing whenever the 'onClicked()' function is called after a 'ng-mouseup' event.
<div ng-mouseenter="onEnter()" ng-mouseup="onClicked()" ng-mouseleave="onExit()">
<div class="row">
<div class="col-sm-9 block">
<span ng-transclude></span>
</div>
<div class="col-sm-3 block" click-anywhere-but-here="onClickElsewhere()">
<div ng-if="normal()"></div>
<div ng-if="focused()"><button class="btn btn-default">Edit <span class="glyphicon glyphicon-pencil"></span></button></div>
<div ng-if="updating()"><button class="btn btn-default">Update <span class="glyphicon glyphicon-ok"></span></button></div>
</div>
</div>
</div>
If you look at the actual onClicked
function below, the problem is caused by writing to the $scope.state
variable (when assigned to either the value normal
or updating
):
angular.module('myApp')
.directive('mutableWidget', [ function() {
return {
transclude: true,
templateUrl: window.grailsSupport.assetsRoot + "app/components/mutable-widget/mutable-widget.html",
restrict: 'A',
scope: true,
link: function($scope, $element, $attribs) {
$scope.state = "normal";
...
$scope.onClicked = function() {
if($scope.state === "updating") {
$scope.state = "normal";
} else {
$scope.state = "updating";
}
console.log("on click called state " + $scope.state);
};
}
};
}]);
For example, if I comment out the statements in the if/else, then the click-anywhere-but-here
directive executes as expected. The code is here:
angular.module('myApp')
.directive('clickAnywhereButHere', function($document, $parse) {
return {
restrict: 'A',
scope: {
callback : '&clickAnywhereButHere'
},
link: function(scope, element, attr, ctrl) {
var handler = function(event) {
if (!element[0].contains(event.target)) {
console.log("doesn't contain target");
scope.$apply(scope.callback(event));
} else {
console.log("does contain target");
}
};
$document.on('click', handler);
scope.$on('$destroy', function() {
$document.off('click', handler);
});
}
}
});
Can anybody explain why the 'click-anywhere-but-here' directive is not executing and what needs to be done to produce the desired behaviour? Some small advice on how to actual debug these issues in a language like Javascript would be hugely appreciated too. When I encounter these problems, solving them often amounts to trial and error and outputting console.log messages in the development tools console.
Thanks in advance!