Dev01
Dev01

Reputation: 14179

How to make textarea not allow or ignore linebreak/newline/return in AngularJS

Is it possible to ignore or not allow line breaks in a textarea in angularjs? The text is used in a pdf generator and I don't want the user to be able to type in a newline then not see it in the pdf. I would rather have the return key ignored all together.

<textarea ng-model="model.text"></textarea>

Upvotes: 12

Views: 10037

Answers (5)

Jette
Jette

Reputation: 2609

Just an update for newer versions of Angular:

component.html:

Catch the keyup event, since at this point the bound variable will contain the new char.

<textarea [(ngModel)]="textAreaContent" (keyup)="keyUp($event)">

component.ts:

Don't look for the Enter key specifically, since the key code can vary between devices. Also that would not catch the unwanted char when user is pasting text. Get every keystroke, and just do a replace.

public textAreaContent;

keyUp(event:KeyboardEvent) {
  console.log(event.key+" pressed");
  this.textAreaContent = this.textAreaContent.replace(/[\r\n]+/," ");
}

Upvotes: 0

Dev01
Dev01

Reputation: 14179

Using Gísli Konráð and midhunsezhi answers I was able to put together a directive that did what I want. Credit should really go to them.

.directive('noNewLines', function() {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function(scope, element, attributes, ngModelController) {
            var model = attributes.ngModel;
            var regex = new RegExp("^[^\n\r]*$");

            // $parsers handle input from the element where the
            // ng-model directive is set
            ngModelController.$parsers.unshift(function(value) {
                if(!value) return value;
                var modelValue = ngModelController.$modelValue;
                var isValid = regex.test(value);
                ngModelController.$setValidity('Does not match pattern', isValid);

                var transformedInput = value.replace(/[\n\r]/g, '');
                if(transformedInput !== value) {
                    ngModelController.$setViewValue(transformedInput);
                    ngModelController.$render();
                }
               return transformedInput;
            });

            // $formatters handle when the model is changed and 
            // the element needs to be updated
            ngModelController.$formatters.unshift(function(value) {
               if(!value) return value;
               var isValid = regex.test(value);
               ngModelController.$setValidity('Does not match pattern', isValid);
               return value;
            });

            element.on('keypress', function(e) {
                var char = String.fromCharCode(e.which);
                var text = angular.element(e.srcElement).val();
                if(!regex.test(char) || !regex.test(text)) {
                    event.preventDefault();   
                }                   
            });

        }
   };
 });

And it's used like this:

<textarea ng-model="text" no-new-lines></textarea>

Upvotes: 6

gislikonrad
gislikonrad

Reputation: 3591

Here's a directive that you could use. It has options to block invalid input and to ignore case.

.directive('taPattern', function() {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function(scope, element, attributes, ngModelController) {
            var pattern = attributes.taPattern;  
            var flag = attributes.taPatternIgnoreCase === true ? 'i' : undefined;
            var blockInvalidInput = attributes.hasOwnProperty('taPatternBlockInvalid');
            var model = attributes.ngModel;
            if(!pattern) return;
            if(pattern[0] != '^')
                pattern = '^' + pattern;
            if(pattern[pattern.length - 1] != '$')
                pattern += '$';

            var regex = new RegExp(pattern, flag);

            // $parsers handle input from the element where the
            // ng-model directive is set
            ngModelController.$parsers.unshift(function(value) {
               if(!value) return value;
               var modelValue = ngModelController.$modelValue;
               var isValid = regex.test(value);
               ngModelController.$setValidity('Does not match pattern', isValid);
               return value;
            });

            // $formatters handle when the model is changed and 
            // the element needs to be updated
            ngModelController.$formatters.unshift(function(value) {
               if(!value) return value;
               var isValid = regex.test(value);
               ngModelController.$setValidity('Does not match pattern', isValid);
               return value;
            });

            if(blockInvalidInput){                    
                element.on('keypress', function(e) {
                    var char = String.fromCharCode(e.which);
                    var text = angular.element(e.srcElement).val();
                    if(!regex.test(char) || !regex.test(text)) {
                        event.preventDefault();   
                    }                   
                });
            }

        }
   };
 });

You can see a demo of it here: https://jsfiddle.net/mr59xf3z/3/

Upvotes: 1

YOU
YOU

Reputation: 123937

Use <input instead of <textarea and set the height like textarea.

input.textarea {
  height: 100px;
  
  word-break: break-word;
  width: 300px;
}
<input class="textarea">

Upvotes: -2

midhunsezhi
midhunsezhi

Reputation: 471

In your controller/directive if you run a regex to remove all the occurrences of '\n' in $scope.model.text, you should get a plain string with no newline characters.

You can refer to this answer to do that: How to replace all occurrences of a string in JavaScript?

If you don't want even the text area to have any line breaks you can add the above logic in a watcher like this:

$scope.$watch('model.text', function(){
  $scope.model.text = $scope.model.text.replace(/\n/g, '');
})

Upvotes: 7

Related Questions