 <p>I believe that the intention of AngularJS inputs and the <code>ngModel</code> direcive is that <strong>invalid input should never end up in the model</strong>. The model should always be valid. The problem with having invalid model is that we might have watchers that fire and take (inappropriate) actions based on invalid model.</p> <p>As I see it, the proper solution here is to plug into the <code>$parsers</code> pipeline and make sure that invalid input doesn't make it into the model. I'm not sure how did you try to approach things or what exactly didn't work for you with <code>$parsers</code> but here is a simple directive that solves your problem (or at least my understanding of the problem):</p> <pre><code>app.directive('customValidation', function(){ return { require: 'ngModel', link: function(scope, element, attrs, modelCtrl) { modelCtrl.$parsers.push(function (inputValue) { var transformedInput = inputValue.toLowerCase().replace(/ /g, ''); if (transformedInput!=inputValue) { modelCtrl.$setViewValue(transformedInput); modelCtrl.$render(); } return transformedInput; }); } }; }); </code></pre> <p>As soon as the above directive is declared it can be used like so:</p> <pre><code>&lt;input ng-model="sth" ng-trim="false" custom-validation&gt; </code></pre> <p>As in solution proposed by @Valentyn Shybanov we need to use the <code>ng-trim</code> directive if we want to disallow spaces at the beginning / end of the input. </p> <p>The advantage of this approach is 2-fold:</p> <ul> <li>Invalid value is not propagated to the model</li> <li>Using a directive it is easy to add this custom validation to any input without duplicating watchers over and over again</li> </ul>