@@ -16,6 +16,10 @@ var INTEGER_REGEXP = /^\s*(\-|\+)?\d+\s*$/;
1616 * @param {string } ng:model Assignable angular expression to data-bind to.
1717 * @param {string= } name Property name of the form under which the widgets is published.
1818 * @param {string= } required Sets `REQUIRED` validation error key if the value is not entered.
19+ * @param {number= } ng:minlength Sets `MINLENGTH` validation error key if the value is shorter than
20+ * minlength.
21+ * @param {number= } ng:maxlength Sets `MAXLENGTH` validation error key if the value is longer than
22+ * maxlength.
1923 * @param {string= } ng:pattern Sets `PATTERN` validation error key if the value does not match the
2024 * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
2125 * patterns defined as scope expressions.
@@ -79,6 +83,10 @@ var INTEGER_REGEXP = /^\s*(\-|\+)?\d+\s*$/;
7983 * @param {string } ng:model Assignable angular expression to data-bind to.
8084 * @param {string= } name Property name of the form under which the widgets is published.
8185 * @param {string= } required Sets `REQUIRED` validation error key if the value is not entered.
86+ * @param {number= } ng:minlength Sets `MINLENGTH` validation error key if the value is shorter than
87+ * minlength.
88+ * @param {number= } ng:maxlength Sets `MAXLENGTH` validation error key if the value is longer than
89+ * maxlength.
8290 * @param {string= } ng:pattern Sets `PATTERN` validation error key if the value does not match the
8391 * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
8492 * patterns defined as scope expressions.
@@ -146,6 +154,10 @@ angularInputType('email', function() {
146154 * @param {string } ng:model Assignable angular expression to data-bind to.
147155 * @param {string= } name Property name of the form under which the widgets is published.
148156 * @param {string= } required Sets `REQUIRED` validation error key if the value is not entered.
157+ * @param {number= } ng:minlength Sets `MINLENGTH` validation error key if the value is shorter than
158+ * minlength.
159+ * @param {number= } ng:maxlength Sets `MAXLENGTH` validation error key if the value is longer than
160+ * maxlength.
149161 * @param {string= } ng:pattern Sets `PATTERN` validation error key if the value does not match the
150162 * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
151163 * patterns defined as scope expressions.
@@ -288,6 +300,10 @@ angularInputType('list', function() {
288300 * @param {string= } min Sets the `MIN` validation error key if the value entered is less then `min`.
289301 * @param {string= } max Sets the `MAX` validation error key if the value entered is greater then `min`.
290302 * @param {string= } required Sets `REQUIRED` validation error key if the value is not entered.
303+ * @param {number= } ng:minlength Sets `MINLENGTH` validation error key if the value is shorter than
304+ * minlength.
305+ * @param {number= } ng:maxlength Sets `MAXLENGTH` validation error key if the value is longer than
306+ * maxlength.
291307 * @param {string= } ng:pattern Sets `PATTERN` validation error key if the value does not match the
292308 * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
293309 * patterns defined as scope expressions.
@@ -353,6 +369,10 @@ angularInputType('number', numericRegexpInputType(NUMBER_REGEXP, 'NUMBER'));
353369 * @param {string= } min Sets the `MIN` validation error key if the value entered is less then `min`.
354370 * @param {string= } max Sets the `MAX` validation error key if the value entered is greater then `min`.
355371 * @param {string= } required Sets `REQUIRED` validation error key if the value is not entered.
372+ * @param {number= } ng:minlength Sets `MINLENGTH` validation error key if the value is shorter than
373+ * minlength.
374+ * @param {number= } ng:maxlength Sets `MAXLENGTH` validation error key if the value is longer than
375+ * maxlength.
356376 * @param {string= } ng:pattern Sets `PATTERN` validation error key if the value does not match the
357377 * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
358378 * patterns defined as scope expressions.
@@ -601,6 +621,10 @@ var HTML5_INPUTS_TYPES = makeMap(
601621 * @param {string } ng:model Assignable angular expression to data-bind to.
602622 * @param {string= } name Property name of the form under which the widgets is published.
603623 * @param {string= } required Sets `REQUIRED` validation error key if the value is not entered.
624+ * @param {number= } ng:minlength Sets `MINLENGTH` validation error key if the value is shorter than
625+ * minlength.
626+ * @param {number= } ng:maxlength Sets `MAXLENGTH` validation error key if the value is longer than
627+ * maxlength.
604628 * @param {string= } ng:pattern Sets `PATTERN` validation error key if the value does not match the
605629 * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
606630 * patterns defined as scope expressions.
@@ -612,32 +636,69 @@ var HTML5_INPUTS_TYPES = makeMap(
612636 <doc:source>
613637 <script>
614638 function Ctrl() {
615- this.text = 'guest';
639+ this.user = {name: 'guest', last: 'visitor'} ;
616640 }
617641 </script>
618642 <div ng:controller="Ctrl">
619643 <form name="myForm">
620- text: <input type="text" name="input" ng:model="text" required>
621- <span class="error" ng:show="myForm.input.$error.REQUIRED">
622- Required!</span>
644+ User name: <input type="text" name="userName" ng:model="user.name" required>
645+ <span class="error" ng:show="myForm.userName.$error.REQUIRED">
646+ Required!</span><br>
647+ Last name: <input type="text" name="lastName" ng:model="user.last"
648+ ng:minlength="3" ng:maxlength="10">
649+ <span class="error" ng:show="myForm.lastName.$error.MINLENGTH">
650+ Too short!</span>
651+ <span class="error" ng:show="myForm.lastName.$error.MAXLENGTH">
652+ Too long!</span><br>
623653 </form>
624- <tt>text = {{text}}</tt><br/>
625- <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
626- <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
627- <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
628- <tt>myForm.$error.REQUIRED = {{!!myForm.$error.REQUIRED}}</tt><br/>
654+ <hr>
655+ <tt>user = {{user}}</tt><br/>
656+ <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>
657+ <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>
658+ <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>
659+ <tt>myForm.userName.$error = {{myForm.lastName.$error}}</tt><br>
660+ <tt>myForm.$valid = {{myForm.$valid}}</tt><br>
661+ <tt>myForm.$error.REQUIRED = {{!!myForm.$error.REQUIRED}}</tt><br>
662+ <tt>myForm.$error.MINLENGTH = {{!!myForm.$error.MINLENGTH}}</tt><br>
663+ <tt>myForm.$error.MAXLENGTH = {{!!myForm.$error.MAXLENGTH}}</tt><br>
629664 </div>
630665 </doc:source>
631666 <doc:scenario>
632667 it('should initialize to model', function() {
633- expect(binding('text')).toEqual('guest');
634- expect(binding('myForm.input.$valid')).toEqual('true');
668+ expect(binding('user')).toEqual('{\n \"last\":\"visitor",\n \"name\":\"guest\"}');
669+ expect(binding('myForm.userName.$valid')).toEqual('true');
670+ expect(binding('myForm.$valid')).toEqual('true');
635671 });
636672
637- it('should be invalid if empty', function() {
638- input('text').enter('');
639- expect(binding('text')).toEqual('');
640- expect(binding('myForm.input.$valid')).toEqual('false');
673+ it('should be invalid if empty when required', function() {
674+ input('user.name').enter('');
675+ expect(binding('user')).toEqual('{\n \"last\":\"visitor",\n \"name\":\"\"}');
676+ expect(binding('myForm.userName.$valid')).toEqual('false');
677+ expect(binding('myForm.$valid')).toEqual('false');
678+ });
679+
680+ it('should be valid if empty when min length is set', function() {
681+ input('user.last').enter('');
682+ expect(binding('user')).toEqual('{\n \"last\":\"",\n \"name\":\"guest\"}');
683+ expect(binding('myForm.lastName.$valid')).toEqual('true');
684+ expect(binding('myForm.$valid')).toEqual('true');
685+ });
686+
687+ it('should be invalid if less than required min length', function() {
688+ input('user.last').enter('xx');
689+ expect(binding('user')).toEqual('{\n \"last\":\"xx",\n \"name\":\"guest\"}');
690+ expect(binding('myForm.lastName.$valid')).toEqual('false');
691+ expect(binding('myForm.lastName.$error')).toMatch(/MINLENGTH/);
692+ expect(binding('myForm.$valid')).toEqual('false');
693+ });
694+
695+ it('should be valid if longer than max length', function() {
696+ input('user.last').enter('some ridiculously long name');
697+ expect(binding('user'))
698+ .toEqual('{\n \"last\":\"some ridiculously long name",\n \"name\":\"guest\"}');
699+ expect(binding('myForm.lastName.$valid')).toEqual('false');
700+ expect(binding('myForm.lastName.$error')).toMatch(/MAXLENGTH/);
701+ expect(binding('myForm.$valid')).toEqual('false');
641702 });
642703 </doc:scenario>
643704 </doc:example>
@@ -656,6 +717,8 @@ angularWidget('input', function(inputElement){
656717 modelScope = this ,
657718 patternMatch , widget ,
658719 pattern = trim ( inputElement . attr ( 'ng:pattern' ) ) ,
720+ minlength = parseInt ( inputElement . attr ( 'ng:minlength' ) , 10 ) ,
721+ maxlength = parseInt ( inputElement . attr ( 'ng:maxlength' ) , 10 ) ,
659722 loadFromScope = type . match ( / ^ \s * \@ \s * ( .* ) / ) ;
660723
661724
@@ -711,15 +774,24 @@ angularWidget('input', function(inputElement){
711774 widget . $pristine = ! ( widget . $dirty = false ) ;
712775
713776 widget . $on ( '$validate' , function ( event ) {
714- var $viewValue = trim ( widget . $viewValue ) ;
715- var inValid = widget . $required && ! $viewValue ;
716- var missMatch = $viewValue && ! patternMatch ( $viewValue ) ;
777+ var $viewValue = trim ( widget . $viewValue ) ,
778+ inValid = widget . $required && ! $viewValue ,
779+ tooLong = maxlength && $viewValue && $viewValue . length > maxlength ,
780+ tooShort = minlength && $viewValue && $viewValue . length < minlength ,
781+ missMatch = $viewValue && ! patternMatch ( $viewValue ) ;
782+
717783 if ( widget . $error . REQUIRED != inValid ) {
718784 widget . $emit ( inValid ? '$invalid' : '$valid' , 'REQUIRED' ) ;
719785 }
720786 if ( widget . $error . PATTERN != missMatch ) {
721787 widget . $emit ( missMatch ? '$invalid' : '$valid' , 'PATTERN' ) ;
722788 }
789+ if ( widget . $error . MINLENGTH != tooShort ) {
790+ widget . $emit ( tooShort ? '$invalid' : '$valid' , 'MINLENGTH' ) ;
791+ }
792+ if ( widget . $error . MAXLENGTH != tooLong ) {
793+ widget . $emit ( tooLong ? '$invalid' : '$valid' , 'MAXLENGTH' ) ;
794+ }
723795 } ) ;
724796
725797 forEach ( [ 'valid' , 'invalid' , 'pristine' , 'dirty' ] , function ( name ) {
0 commit comments