This should be straight forward but haven't found a solution yet.
I have an input
in a form
. I want to detect when a user has interacted with the input and run a javascript function once if they have.
I have been thinking of using a $watch
to detect if the input
element has the class ng-dirty
and if it has, run js function and unbind the watch.
Is there a better way? It would be great if you could provide an example.
This is a simple directive that should do what you're looking for.
angular.module('myApp', [])
.controller('MyCtrl', function($scope) {
$scope.bar = function() {
console.log('bar was called!');
$scope.barWasCalled = true;
};
})
.directive('once', function() {
return {
require: 'ngModel',
scope: {
fn: '&once'
},
link: function($scope, $element, $attrs, ngModel) {
// add a listener and save the index for removal
var idx = ngModel.$viewChangeListeners.push(function() {
// user typed, run the function
$scope.fn();
// remove the listener
ngModel.$viewChangeListeners.splice(idx, 1);
}) - 1;
}
};
})
;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
<input type="text" ng-model="foo" once="bar()" placeholder="type something...">
<div ng-show="barWasCalled">Bar was called!</div>
</div>
$viewChangeListener
offers just a touch better performance than a $watch
, though it is nominal anyway.
Remember to put any kind of DOM related behaviors such as this into directives. That keeps things light and neat.