14

Simple example: I have a textarea and want to provide additional behavior to it: do something on enter key and go to next line on shift + enter

I suppose that I should provide additional directive to add that behavior. And I've done this: http://jsbin.com/oruvuy/1/edit

P.S. One hackie thing seems strange for me: I invoke $digest() manually. Is it ok? Any thoughts?

JS:

angular.module('Chat', [])
  .directive('enterSubmit', function () {
    return {
      restrict: 'A',
      link: function (scope, element, attrs) {
        var submit;

        $(element).on({
          keydown: function (e) {
            submit = false;

            if (e.which === 13 && !e.shiftKey) {
              submit = true;
              e.preventDefault();
            }
          },

          keyup: function () {
            if (submit) {
              scope.$eval( attrs.enterSubmit );

              // flush model changes manually
              scope.$digest();
            }
          }
        });
      }
    };
  });

function ChatCtrl($scope) {
  $scope.messages = [{
    text: 'Sample Message',
    datetime: new Date()
  }];

  $scope.add = function () {
    $scope.messages.push({
      text: $scope.message,
      datetime: new Date()
    });
    $scope.message = '';
  };

  $scope.message = '';
}
<body ng-controller="ChatCtrl">

  <h1>Leave message:</h1>
  <form>
    <div class='hint'>Click &lt;Enter&gt; to submit :)</div>
    <textarea
      cols="30"
      rows="5"
      ng-model="message"
      enter-submit='add()'
    ></textarea>
    <br />
    <button type="submit" ng-click="add()">Send message!</button>
  </form>

  <h3>Messages list:</h3>
  <table>
    <tr>
      <th>Text</th>
      <th>Date</th>
    </tr>
    <tr ng-repeat="message in messages">
      <td class='text'>{{message.text}}</td>
      <td class='date'>{{message.datetime | date:"HH:mm:ss"}}</td>
    </tr>
  </table>

</body>

But is it correct way to do that?

ValeriiVasin
  • 8,628
  • 11
  • 58
  • 78

1 Answers1

12

Yes, binding events in the directive's linking function is exactly what you want to do.

Calling $digest is not hacky - the messages in your example are being added to the model on keyup, and Angular won't digest those changes until something tells it to. It will actually be digested on the next keydown, but since you need the $digest to happen after your keyup, you're having to call it manually.

jingman
  • 415
  • 3
  • 10
  • Great, thanks for explanation. But I've not been understood about events. AngularJS is listening for all events on the page and then check the state of every objects? Is there any understandable article about that? I've read on AngularJS about that, but it's to hard to understand quickly. – ValeriiVasin Feb 17 '13 at 22:55
  • I recommend [this StackOverflow question](http://stackoverflow.com/questions/12463902/how-does-the-binding-and-digesting-work-in-angularjs) as a good reference. – jingman Feb 17 '13 at 23:10