How to observe custom events in AngularJS?

12,561

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.

Share:
12,561

Related videos on Youtube

ValeriiVasin
Author by

ValeriiVasin

Web developer. JavaScript lover.

Updated on July 07, 2022

Comments

  • ValeriiVasin
    ValeriiVasin almost 2 years

    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
    ValeriiVasin over 11 years
    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.
  • jingman
    jingman over 11 years
    I recommend this StackOverflow question as a good reference.