AngularJS Question

AngularJs input field with ng-model with filter issue

I have several input fields and i wish to validate user input if is only white space. I try with directive or with filter. I prefer not to use $watch because there are too many input fields. What I need is: If User set only blank spaces in input field some function or directive to clean this white spaces.
I can do this with jQuery or vanilla JS, but I prefer this result to be in angular way.

Where I`m wrong in directive or in filter

This is my code:

angular.module('app')
.directive('customSpaceValidation', ['$filter', function ($filter) {
return {
require: '?ngModel',
link: function (scope, elem, attrs, ctrl) {
if (!ctrl.replace(/\s/g, '').length) {
ctrl = "";
}
return ctrl;
}
};
}])
.filter('nospace', function () {
return function (value) {
if (!value.replace(/\s/g, '').length) {
value = "";
}
return value;
};
})


this is html with directive:

<input type="text" class="form-control" id="inputKey" ng-model="channel.key" customSpaceValidation data-ng-trim="false" ng-required="true" name="inputKey" required />


this is html with filter

<input type="text" class="form-control" id="inputKey" ng-model="channel.key | filter : nospace" data-ng-trim="false" ng-required="true" name="inputKey" required />


Filter trow exceptions:

ng-table-export.src.js:45 TypeError: ngModelSet is not a function
at NgModelController.$$writeModelToScope (ng-table-export.src.js:45)
at writeToModelIfNeeded (ng-table-export.src.js:45)
at ng-table-export.src.js:45
at validationDone (ng-table-export.src.js:45)
at processAsyncValidators (ng-table-export.src.js:45)
at NgModelController.$$runValidators (ng-table-export.src.js:45)
at NgModelController.$$parseAndValidate (ng-table-export.src.js:45)
at NgModelController.$commitViewValue (ng-table-export.src.js:45)
at ng-table-export.src.js:45
at Scope.$eval (ng-table-export.src.js:45)

Answer

You cannot use ng-model with filter because filtering is a one-way operation, while ng-model is two-way binding. The directive has to be snake-cased instead of camelCased when used in the HTML, i.e. custom-space-validation.

To actually validate, you need a validator:

.directive('customSpaceValidation', [function() {
    var RE = /^\s+$/;

    return {
        require: 'ngModel',
        link: function (scope, elem, attrs, ngModel) {
            ngModel.$validators['customSpace'] = function(modelValue, viewValue) {
                var value = modelValue || viewValue;
                return !RE.text(value);
            };
        }
    };
}])