0

I'm trying to understand directives, and I'm having problems with two way data binding.

My directive will be used to submit a form when "enter" is pressed in a textarea.

I found a solution in another SO thread (see the code below in the scope definition of the directive), but I don't like it because it means that if I change the model name, I need to change the directive as well..

--> Here is the problem in codepen.io

Here is the html part:

<div ng-app="testApp" ng-controller="MyController">
  <textarea ng-model="foo" enter-submit="submit()"></textarea><br/>
  Binding: {{foo}}
</div>

Here is the javascript part:

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

function MyController($scope) {

  $scope.foo = "bar"

  $scope.submit = function() {
    console.log("Submitting form");
  }
}

app.directive('enterSubmit', function () {
    return {
      restrict: 'A',
      scope: {
        submitFn: '&enterSubmit',
        foo: '=ngModel'      // <------------------- dont't like this solution
      },
      link: function (scope, elem, attrs) {

        elem.bind('keydown', function(event) {
          var code = event.keyCode || event.which;

          if (code === 13) {
            if (!event.shiftKey) {
              event.preventDefault();
              scope.submitFn();
            }
          }
        });
      }
    }
  });

Thanks for your help !

Community
  • 1
  • 1
ybycode
  • 171
  • 3
  • 17

1 Answers1

0

When multiple directives are used on an element, normally you don't want any of them to use an isolate scope, since that forces all of them to use the isolate scope. In particular, isolate scopes should not be used with ng-model – see Can I use ng-model with isolated scope?.

I suggest creating no new scope (the default, i.e., scope: false):

app.directive('enterSubmit', function () {
    return {
      restrict: 'A',
      //scope: {
      //  submitFn: '&enterSubmit',
      //  foo: '=ngModel' // <------------------- dont't like this solution
      //},
      link: function (scope, elem, attrs) {
        elem.bind('keydown', function(event) {
          var code = event.keyCode || event.which;
          if (code === 13) {
            if (!event.shiftKey) {
              event.preventDefault();
              scope.$apply(attrs.enterSubmit);
            }
          }
        });
      }
    }
  });
Community
  • 1
  • 1
Mark Rajcok
  • 362,217
  • 114
  • 495
  • 492
  • Thank you, I used an isolate scope because I wanted to use the controller function to submit, but didn't know about 'scope.$apply'. Your explanation makes sense, and it works ! – ybycode Aug 14 '13 at 14:25
  • @y__b__y, you can also use $eval: `scope.$eval(attrs.enterSubmit)` if you don't need a digest cycle to run. – Mark Rajcok Aug 14 '13 at 14:34