4

I'm using the directive from this answer to run a function when the enter key is pressed in an input field.

How can I pass the value of the input field element.val() to the function the directive calls? Or pass the input field element to the function, to clear the value after it's retrieved.

HTML

<input type="text" ng-enter="newField()" />

JS

app.directive('ngEnter', function() {
    return function(scope, element, attrs) {
        element.bind("keydown keypress", function(event) {
            if(event.which === 13) {
                element.val(); // value of input field

                scope.$apply(function(){
                    scope.$eval(attrs.ngEnter); // passed to this function
                });

                event.preventDefault();
            }
        });
    };
});
Community
  • 1
  • 1
nathancahill
  • 10,452
  • 9
  • 51
  • 91

2 Answers2

3

You could just do this:

var func = scope.$eval(attrs.ngEnter);
func();

and have the controller take care of the value logic. See the code below. Live demo (click).

Also, I don't recommend prefixing your custom directives with ng. I suggest coming up with your own prefix as a namespace. ng is for Angular's core. In my examples, I am using my-enter rather than ng-enter.

Sample markup:

  <input 
    type="text" 
    ng-model="foo" 
    my-enter="myFunc"
    placeholder="Type stuff!"
  >
  <p ng-repeat="val in cachedVals track by $index">{{val}}</p>

JavaScript:

var app = angular.module('myApp', []);

app.controller('myCtrl', function($scope) {
  $scope.cachedVals = [];
  $scope.foo = '';
  $scope.myFunc = function() {
    $scope.cachedVals.push($scope.foo);
    $scope.foo = '';
  };
});

app.directive('myEnter', function() {
  return function(scope, element, attrs) {
    element.bind("keydown keypress", function(event) {
      if(event.which === 13) {
        scope.$apply(function(){
          var func = scope.$eval(attrs.myEnter);
          func();
        });
        event.preventDefault();
      }
    });
  };
});

Here's an example with an isolated scope - you don't need to $eval.

app.directive('myEnter', function() {
  return {
    scope: {
      func: '=myEnter'
    },
    link: function(scope, element, attrs) {
      element.bind("keydown keypress", function(event) {
        if(event.which === 13) {  
          scope.$apply(function(){
            scope.func();
          });  
          event.preventDefault();
        }
      });
    }
  };
});
m59
  • 43,214
  • 14
  • 119
  • 136
  • Hmm.. not quite. I'm just trying to get the value when the user hits enter, use it, then clear the input field. ng-change executes on each keypress. – nathancahill Jan 22 '14 at 03:39
  • @nathancahill yeah, I'm working on the directive and see that now. That was just my first thought. I should be done soon! – m59 Jan 22 '14 at 03:40
  • @nathancahill I still need to make an improvement, but my original recommendation works. – m59 Jan 22 '14 at 03:46
  • Is $eval or scope.$apply better? – nathancahill Jan 22 '14 at 03:54
  • @nathancahill hmm? They are unrelated. The directive at the bottom of my post is the one I suggest. `$apply` is needed because you're firing angular code outside of angular (the event block). `$eval` gets a scope value from a string of its name. – m59 Jan 22 '14 at 03:57
  • @nathancahill I updated one last time. Check it out - important note about `ng`. – m59 Jan 22 '14 at 04:02
-1

Have you tried ng-submit? I have created a fiddle to show you how do to what you are after without requiring your own directive.

http://jsfiddle.net/a6k7g/

Obviously this answer depends on your requirements, and the form complexity.

Matt Way
  • 32,319
  • 10
  • 79
  • 85