title: Using an AngularJS directive, how do I bind to keyup event on input field and revert model to previous value if it fails a regular expression check?
body: <p>Doing a quick POC in AngularJS to only allow specific input into a text box.</p>
  
  <p>The goal is to check the value every time the user types a new character, if it fails the regular expression check, we need to either reject the character or roll it back to the previous value.</p>
  
  <p>The way I see it, here are my 2 options:
  1. Bind to keypress event, check what the new value would be against a regex, and return false if it fails, preventing the character from being accepted into the text box
  2. Bind to keyup event, check what the new value is against a regex, and if it fails, revert it to the previous value</p>
  
  <p>How can I accomplish this from my directive?</p>
  
  <pre><code>var currencyRegEx = /^\$?\-?([1-9]{1}[0-9]{0,2}(\,\d{3})*(\.\d{0,2})?|[1-9]{1}\d{0,}(\.\d{0,2})?|0(\.\d{0,2})?|(\.\d{1,2}))$|^\-?\$?([1-9]{1}\d{0,2}(\,\d{3})*(\.\d{0,2})?|[1-9]{1}\d{0,}(\.\d{0,2})?|0(\.\d{0,2})?|(\.\d{1,2}))$|^\(\$?([1-9]{1}\d{0,2}(\,\d{3})*(\.\d{0,2})?|[1-9]{1}\d{0,}(\.\d{0,2})?|0(\.\d{0,2})?|(\.\d{1,2}))\)$/;
  app.directive("currencyInput", function () {
      return {
          restrict: "A",
          scope: {
          },
          require: 'ngModel',
          link: function (scope, element, attrs, ngModelCtrl) {
              $(element).bind('keypress', function (event) {
                  // TODO: Get what new value would be
                  var newValue = "...";
                  return currencyRegEx.test(newValue);
  
              });
              $(element).bind('keyup', function (event) {
                  var newValue = $(this).val();
                  if (!currencyRegEx.test(newValue)) {                
                      // TODO: Revert to previous value
                  }
              });
          }
      }
  });
  
  &lt;input type="text" class="form-control" ng-model="item.paymentAmount" currency-input /&gt;
  </code></pre>
  
  <p><strong>EDIT w/ SOLUTION</strong>
  Here is the current solution we have in place in order to prevent non-digit input and rollback invalid currency value. </p>
  
  <p>First, we created a new property "scope.prevValue" to hold the last valid value entered by the user. Then, on "keypress" we check to make sure the user typed a digit, comma, or period. Finally, on "keyup", we check the new value against the currency regex and rollback if needed.</p>
  
  <pre><code>var currencyRegEx = /^\$?\-?([1-9]{1}[0-9]{0,2}(\,\d{3})*(\.\d{0,2})?|[1-9]{1}\d{0,}(\.\d{0,2})?|0(\.\d{0,2})?|(\.\d{1,2}))$|^\-?\$?([1-9]{1}\d{0,2}(\,\d{3})*(\.\d{0,2})?|[1-9]{1}\d{0,}(\.\d{0,2})?|0(\.\d{0,2})?|(\.\d{1,2}))$|^\(\$?([1-9]{1}\d{0,2}(\,\d{3})*(\.\d{0,2})?|[1-9]{1}\d{0,}(\.\d{0,2})?|0(\.\d{0,2})?|(\.\d{1,2}))\)$/;
  var digitRegex = /^[0-9]*$/;
  app.directive("currencyInput", function () {
      return {
          restrict: "A",
          scope: {},
          require: 'ngModel',
          link: function (scope, element, attrs, ngModelCtrl) {
              scope.prevValue = '';
  
              $(element).on('keypress', function(event) {
                  var validAlphaChars = ['.', ','];
                  var enteredCharacter = String.fromCharCode(event.charCode != null ? event.charCode : event.keyCode);
                  if (validAlphaChars.indexOf(enteredCharacter) &lt; 0 &amp;&amp; !digitRegex.test(enteredCharacter)) {
                      return false;
                  }
              });
  
              $(element).on('keyup', function (event) {
                  var newValue = $(element).val();
                  if (newValue.length &gt; 0 &amp;&amp; !currencyRegEx.test(newValue)) {
                      $(element).val(scope.prevValue);
                      return false;
                  } else {
                      scope.prevValue = $(element).val();
                  }
              });
          }
      });
  </code></pre>
  
  <p><strong>EDIT w/ SOLUTION #2 (using Steve_at_IDV's approach on accepted answer)</strong></p>
  
  <pre><code>var currencyRegEx = /^\$?\-?([1-9]{1}[0-9]{0,2}(\,\d{3})*(\.\d{0,2})?|[1-9]{1}\d{0,}(\.\d{0,2})?|0(\.\d{0,2})?|(\.\d{1,2}))$|^\-?\$?([1-9]{1}\d{0,2}(\,\d{3})*(\.\d{0,2})?|[1-9]{1}\d{0,}(\.\d{0,2})?|0(\.\d{0,2})?|(\.\d{1,2}))$|^\(\$?([1-9]{1}\d{0,2}(\,\d{3})*(\.\d{0,2})?|[1-9]{1}\d{0,}(\.\d{0,2})?|0(\.\d{0,2})?|(\.\d{1,2}))\)$/;
  app.directive("currencyInput", function () {
      return {
          restrict: "A",
          scope: {},
          require: 'ngModel',
          link: function (scope, element, attrs, ngModelCtrl) {
              ngModelCtrl.$parsers.push(function (value) {
                  if (value.length &gt; 0 &amp;&amp; value != '.' &amp;&amp; !currencyRegEx.test(value)) {
                      var prevValue = ngModelCtrl.$modelValue;
                      ngModelCtrl.$setViewValue(prevValue)
                      ngModelCtrl.$render();
                      return prevValue;
                  }
  
                  return value;
              });
          }
      }
  });
  </code></pre>