71

I've tried using the uppercase filter but it does not work. I've tried doing it two ways:

<input type="text" ng-model="test" uppercase/>

and

<input type="text" ng-model="{{test | uppercase}}"/>

The 2nd triggers a javascript error:

Syntax Error: Token 'test' is unexpected, expecting [:]

I want the text to be forced to uppercase as the user types in the textbox.

How can I do that?

Simon MᶜKenzie
  • 8,344
  • 13
  • 50
  • 77
Sam
  • 13,934
  • 26
  • 108
  • 194

14 Answers14

107

Please see the other answer below, which is superior to this one.

this answer is based on the answer here: How to autocapitalize the first character in an input field in AngularJS?.

I'd imagine that what you'd want would be a parser function like this:

angular
  .module('myApp', [])
  .directive('capitalize', function() {
    return {
      require: 'ngModel',
      link: function(scope, element, attrs, modelCtrl) {
        var capitalize = function(inputValue) {
          if (inputValue == undefined) inputValue = '';
          var capitalized = inputValue.toUpperCase();
          if (capitalized !== inputValue) {
            // see where the cursor is before the update so that we can set it back
            var selection = element[0].selectionStart;
            modelCtrl.$setViewValue(capitalized);
            modelCtrl.$render();
            // set back the cursor after rendering
            element[0].selectionStart = selection;
            element[0].selectionEnd = selection;
          }
          return capitalized;
        }
        modelCtrl.$parsers.push(capitalize);
        capitalize(scope[attrs.ngModel]); // capitalize initial value
      }
    };
  });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app="myApp">
  <input type="text" ng-model="name" capitalize>
</div>
GHC
  • 2,658
  • 5
  • 30
  • 35
  • perfect, that's what I needed. I didn't see this example. I think the uppercase filter was a bit mis-leading for me.... Thanks – Sam May 06 '13 at 07:33
  • 4
    This is a handy directive! It may be helpful if you tested for the existence of inputValue before calling a method on it however. – Matt Jensen Oct 14 '13 at 22:30
  • 3
    Changed the push(capitalize) to unshift(capitalize), but other than that it worked fine. Thx. – Christophe Geers Jul 16 '14 at 07:39
  • +1 I was stuck for over an hour trying to figure out why `$parsers` and `$formatters` were not updating the input control. Adding the calls to `$setViewValue` and `$render` did the trick. I'm going to ask the Angular team to add this to the docs. – Reactgular Oct 25 '14 at 22:11
  • 10
    you could store the selectionStart of the input before and reset after rendered, so the cursor would not move to the end of the string after each key press. ```var selection = element[0].selectionStart; modelCtrl.$setViewValue(capitalized); modelCtrl.$render(); element[0].selectionStart = selection; element[0].selectionEnd = selection; ``` – rucsi Dec 11 '15 at 10:34
  • Add modelCtrl.$commitViewValue() after modelCtrl.$render(), because without doing this, a potential ng-pattern validation on the input will check the non-capitalized value. :) – andrea.spot. Jun 20 '17 at 15:30
  • Hi but this fails if you are editing the same field. for e.g. existing text in the field is East. I want to update as NorthEast. The time you enter N your cursor foucus shifts to the end – AkRoy Jun 19 '18 at 10:33
  • This failed for input type = "email" as email input types does not support selection. – Biswas Khayargoli Mar 17 '19 at 17:30
68

The accepted answer causes problems if someone tries to enter a lowercase letter at the beginning of an existing string.. The cursor moves to the end of the string after each key press. Here's a simple solution that addresses all the issues:

directive('uppercased', function() {
    return {
        require: 'ngModel',
        link: function(scope, element, attrs, modelCtrl) {
            modelCtrl.$parsers.push(function(input) {
                return input ? input.toUpperCase() : "";
            });
            element.css("text-transform","uppercase");
        }
    };
})

Here's a fiddle: http://jsfiddle.net/36qp9ekL/1710/

Karen Zilles
  • 7,633
  • 3
  • 34
  • 33
  • 4
    Its to be noted however that the CSS text-transform merely makes the text on-screen uppercase, but the value bound to the model is not. While the accepted answer may have other unintended consequences (like the cursor bumping to the end), this one may too, depending on the requirements. – Mattygabe Feb 20 '15 at 15:36
  • 3
    The value bound to the model is upper cased by the $parser. Or are you referring to the value attribute of the input element? In that case you are correct. – Karen Zilles Feb 20 '15 at 18:30
  • 1
    Ah - wasn't referring to that necessarily and missed the parser piece somehow. I kind of skimmed your example and my mind instantly focused on the text-transform being applied to the element. I'll smack my own hand for skimming instead of reading :) – Mattygabe Feb 20 '15 at 18:48
  • Correct me if I'm wrong but I think `$(element)` and `element` are equivalent. – robert4 Mar 02 '15 at 12:46
  • You are correct. I was thinking element was the unwrapped dom element, but it comes prewrapped. I've updated the code (and added a fiddle too). – Karen Zilles Mar 02 '15 at 19:30
  • Note that **THIS ONE** is uppercase -- **This One** is *Title Case*. **lowerCamelCase**. **UpperCamelCase**. – Cody Jul 22 '15 at 18:43
  • Hi, @Cody. What are you trying to note here? The question asks for uppercase and this directive provides uppercase. – Karen Zilles Jul 22 '15 at 18:46
  • Just contributing some context here as many times the semantics get a little butchered -- just adding it anecdotally for what its worth. – Cody Jul 23 '15 at 17:30
  • Thanks. The only inconvenient is that if there is a placeholder it will also be in uppercase. – pgrodrigues Oct 06 '15 at 10:33
  • 3
    See [this answer](http://stackoverflow.com/a/22415134/3894163) to keep placeholder as is – Jaydo May 13 '16 at 05:22
35

The idea is to show (not transform) the string as uppercase at client side and transform into uppercase at server side (users can always control what happens at client side). So:

1) in the html:

<input id="test" type="text" ng-model="test">

here no uppercase transformation.

2) in the css:

#test {text-transform: uppercase;}

data is shown as uppercase, but actually still lowercase, if user typed in lowercase. 3) turn the string into uppercase at server side when inserting into database.

= = = = = for playing around, can try follow:

<input type="text" ng-model="test" ng-change="test=test.toUpperCase();">
<input type="text" ng-model="test" ng-blur="test=test.toUpperCase();">

but I think ng-change or ng-blur ways are not necessary for your case.

Timathon
  • 1,049
  • 9
  • 11
  • Now this works and its simple! So that's the best thing! :) Thanks P.S i used ng-keydown as well to make sure user sees the magic sooner :) – BlackBurn027 May 02 '17 at 07:57
31

You cannot make filter on ng-model since it has to be assignable. the workaround is either parser, or simply ng-change.

<input ng-model="some" ng-change="some = (some | uppercase)"  />

This should work.

qwerty_igor
  • 919
  • 8
  • 14
17

When used with Bootstrap, just add text-uppercase to input's class attribute.

Ludovic Guillaume
  • 3,237
  • 1
  • 24
  • 41
  • 1
    You can add this then : `::-webkit-input-placeholder { text-transform: none; } ::-moz-placeholder { text-transform: none; } :-ms-input-placeholder { text-transform: none; } input:-moz-placeholder { text-transform: none; }`. Add `.text-uppercase` to this classes if needed. – Ludovic Guillaume Feb 05 '15 at 11:32
  • It worked on the user interface, but the model value is still lowecase – Diego Oct 06 '15 at 17:57
  • 1
    If you want to change the model to uppercase, you will need to use model controller's $parsers like explained above. This solution is visual only. – Ludovic Guillaume Oct 06 '15 at 18:08
  • You can use bootstrap class for visual purpose, and in your controller, using the toUperCase() function before using your model – Emmanuel P. Aug 31 '16 at 16:32
6
one of the simple way is,
<input type="text" ng-model="test" ng-change="upper(test)/>

just do below 2 line code in your js file,
$scope.upper = function(test){
$scope.test = test.toUpperCase();
}

here is my fiddle http://jsfiddle.net/mzmmohideen/36qp9ekL/299/

Mohideen bin Mohammed
  • 18,813
  • 10
  • 112
  • 118
  • This solution is wonderful - just the few lines that it needs. It does seem to cancel out my `ng-pattern` I am using to validate a MAC address using a regex. Any ideas on how I can get both to work? https://jsfiddle.net/630dkL15/ – SpaceNinja Apr 04 '16 at 19:56
  • I cant get your question... U got uppercase for your input and you going to compare it with mac_regex is it right? and in your jsfiddle found one external link, it describes about uppercase the given text while binding not for ng-model or run time inputs. that will work for angular output which will bind within it {{}} – Mohideen bin Mohammed Apr 05 '16 at 06:59
  • 1
    https://jsfiddle.net/mzmmohideen/oqzs0w8m/ here is my JSFIDDLE , here when you enter mac address correctly means it shows correct else it return false and dont worry about lower case, when u entered mac correctly at the end it will become upper case – Mohideen bin Mohammed Apr 05 '16 at 07:01
  • @SpaceNinja did u got what you want? – Mohideen bin Mohammed Apr 06 '16 at 07:19
  • I like your solution, I may use it if I cannot find a solution that capitalizes AS the user types instead of at the end when it finally does validation. I was hoping to see what the issue was with the conflict of ng-pattern and ng-change - http://jsfiddle.net/rod9pLom/3/ – SpaceNinja Apr 10 '16 at 21:14
2

This will not work at all.

ng-model is for specifying which field / property from the scope should be bound to the model. Also, ng-model does not accept an expression as value. Expressions in angular.js are things between {{ and }}.

The uppercase filter could used in the output and everywhere where expressions are allowed.

You cannot do what you want to do, but you could use CSS's text-transform to at least display everything in uppercase.

If you want to have the value of a text field in uppercase letters you can achieve this with some custom JavaScript.

In your controller:

$scope.$watch('test', function(newValue, oldValue) {
  $scope.$apply(function() {
    $scope.test = newValue.toUpperCase();
  }
});
Simon MᶜKenzie
  • 8,344
  • 13
  • 50
  • 77
TheHippo
  • 61,720
  • 15
  • 75
  • 100
  • good answer, I'll take GHC's though as it is closer to what I want (using an attribute in the view) – Sam May 06 '13 at 07:32
2

Don't forget to include 'ngSanitize' in your module!

app.directive('capitalize', function() {
    return {
        restrict: 'A', // only activate on element attribute
        require: '?ngModel',
        link : function(scope, element, attrs, modelCtrl) {
            var capitalize = function(inputValue) {
                if(inputValue) {
                    var capitalized = inputValue.toUpperCase();
                    if (capitalized !== inputValue) {
                        modelCtrl.$setViewValue(capitalized);
                        modelCtrl.$render();
                    }
                    return capitalized;
                }
            };
            modelCtrl.$parsers.push(capitalize);
            capitalize(scope[attrs.ngModel]); // capitalize initial value
        }
    };

});

  • Pay attention to "?" in "require: '?ngModel',"... only then worked my application.

  • "if(inputValue) {...}" For no undefined error occurs

Deivid
  • 21
  • 1
1

When using bootstrap:

First approach: Using class text-uppercase

<input  type="text" class="text-uppercase" >

Second approach: Using style which can be applied with existing class

<input  type="text" class="form-control" style="text-transform: uppercase;">

Here is my stackBlitz: https://angular-nvd7v6forceuppercase.stackblitz.io

Palash Roy
  • 1,547
  • 1
  • 15
  • 11
0

it is just an alternative , you can use this " text- transform : capitalize ; " in your css and the text entry will be capitalized. unless the user types it in capital letters everywhere.

it is just an alternative ^^

0

To improve the answer by Karl Zilles this is my revision of his solution. In my version the placeholder isn't changed to uppercase and works also if you want to do a regex on the string. It also take the "type" of the input string (null or undefined or empty):

var REGEX = /^[a-z]+$/i;
myApp.directive('cf', function() {
    return {
        require: 'ngModel',
        link: function(scope, elm, attrs, ctrl) {
            ctrl.$validators.cf = function(modelValue, viewValue) {
            ctrl.$parsers.push(function(input) {
                elm.css("text-transform", (input) ? "uppercase" : "");
                return input ? input.toUpperCase() : input;
            });
            return (!(ctrl.$isEmpty(modelValue)) && (REGEX.test(viewValue)));
        }
    }
}
});
Community
  • 1
  • 1
Matteo Gaggiano
  • 1,254
  • 15
  • 28
0

Solution with cursor shift fix

.directive('titleCase', function () {
        return {
            restrict: 'A',
            require: 'ngModel',
            link: function (scope, element, attrs, modelCtrl) {
                var titleCase = function (input) {
                    let first = element[0].selectionStart;
                    let last = element[0].selectionEnd;
                    input = input || '';
                    let retInput = input.replace(/\w\S*/g, function (txt) { return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); });
                    if (input !== retInput) {
                        modelCtrl.$setViewValue(retInput);
                        attrs.ngModel = retInput;
                        modelCtrl.$render();
                        if (!scope.$$phase) {
                            scope.$apply(); // launch digest;
                        }
                    }
                    element[0].selectionStart = first;
                    element[0].selectionEnd = last;
                    return retInput;
                };
                modelCtrl.$parsers.push(titleCase);
                titleCase(scope[attrs.ngModel]);  // Title case  initial value
            }
        };
    });
G5W
  • 36,531
  • 10
  • 47
  • 80
AkRoy
  • 343
  • 4
  • 10
0

If you want to change model and value, use:

angular.module('MyApp').directive('uppercased', function() {
    return {
        require: 'ngModel',
        link: function(scope, element, attrs, ngModel) {
            element.bind("blur change input", function () {
                ngModel.$setViewValue($(this).val().toUpperCase());
                $(this).val($(this).val().toUpperCase());
            });
            element.css("text-transform","uppercase");
        }
    };
});

Then add uppercased to your html input text

<input  type="text" uppercased />
-1

I would just use the filter itself in the controller:

 $filter('uppercase')(this.yourProperty)

just keep in mind that, if you you are going to use it inside a controller, for example, you need to inject this filter:

app.controller('FooController', ['$filter', function($filter) ...