aboutsummaryrefslogtreecommitdiffstats
path: root/src/widget/input.js
diff options
context:
space:
mode:
authorVojta Jina2012-02-23 19:47:58 -0800
committerVojta Jina2012-02-28 18:22:35 -0800
commit139e1b09a94f60b351cc961d8bfd882c0b8ba594 (patch)
treee4403c52a9be8db33a991420056c865855bdd6f7 /src/widget/input.js
parent60743fc52aea9eabee58258a31f4ba465013cb4e (diff)
downloadangular.js-139e1b09a94f60b351cc961d8bfd882c0b8ba594.tar.bz2
docs(forms): Update API docs for forms
- API forms (ng:model + controller, form + controller) - fix some broken links - ng:change, ng:model-instant
Diffstat (limited to 'src/widget/input.js')
-rw-r--r--src/widget/input.js1242
1 files changed, 702 insertions, 540 deletions
diff --git a/src/widget/input.js b/src/widget/input.js
index 6c95327c..f3590e7d 100644
--- a/src/widget/input.js
+++ b/src/widget/input.js
@@ -1,568 +1,358 @@
'use strict';
-
var URL_REGEXP = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/;
var EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$/;
var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/;
+var inputType = {
-/**
- * @ngdoc inputType
- * @name angular.inputType.text
- *
- * @description
- * Standard HTML text input with angular data binding.
- *
- * @param {string} ng:model Assignable angular expression to data-bind to.
- * @param {string=} name Property name of the form under which the widgets is published.
- * @param {string=} required Sets `REQUIRED` validation error key if the value is not entered.
- * @param {number=} ng:minlength Sets `MINLENGTH` validation error key if the value is shorter than
- * minlength.
- * @param {number=} ng:maxlength Sets `MAXLENGTH` validation error key if the value is longer than
- * maxlength.
- * @param {string=} ng:pattern Sets `PATTERN` validation error key if the value does not match the
- * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
- * patterns defined as scope expressions.
- * @param {string=} ng:change Angular expression to be executed when input changes due to user
- * interaction with the input element.
- *
- * @example
- <doc:example>
- <doc:source>
- <script>
- function Ctrl($scope) {
- $scope.text = 'guest';
- $scope.word = /^\w*$/;
- }
- </script>
- <form name="myForm" ng:controller="Ctrl">
- Single word: <input type="text" name="input" ng:model="text"
- ng:pattern="word" required>
- <span class="error" ng:show="myForm.input.error.REQUIRED">
- Required!</span>
- <span class="error" ng:show="myForm.input.error.PATTERN">
- Single word only!</span>
-
- <tt>text = {{text}}</tt><br/>
- <tt>myForm.input.valid = {{myForm.input.valid}}</tt><br/>
- <tt>myForm.input.error = {{myForm.input.error}}</tt><br/>
- <tt>myForm.valid = {{myForm.valid}}</tt><br/>
- <tt>myForm.error.REQUIRED = {{!!myForm.error.REQUIRED}}</tt><br/>
- </form>
- </doc:source>
- <doc:scenario>
- it('should initialize to model', function() {
- expect(binding('text')).toEqual('guest');
- expect(binding('myForm.input.valid')).toEqual('true');
- });
-
- it('should be invalid if empty', function() {
- input('text').enter('');
- expect(binding('text')).toEqual('');
- expect(binding('myForm.input.valid')).toEqual('false');
- });
-
- it('should be invalid if multi word', function() {
- input('text').enter('hello world');
- expect(binding('myForm.input.valid')).toEqual('false');
- });
- </doc:scenario>
- </doc:example>
- */
-
-
-/**
- * @ngdoc inputType
- * @name angular.inputType.email
- *
- * @description
- * Text input with email validation. Sets the `EMAIL` validation error key if not a valid email
- * address.
- *
- * @param {string} ng:model Assignable angular expression to data-bind to.
- * @param {string=} name Property name of the form under which the widgets is published.
- * @param {string=} required Sets `REQUIRED` validation error key if the value is not entered.
- * @param {number=} ng:minlength Sets `MINLENGTH` validation error key if the value is shorter than
- * minlength.
- * @param {number=} ng:maxlength Sets `MAXLENGTH` validation error key if the value is longer than
- * maxlength.
- * @param {string=} ng:pattern Sets `PATTERN` validation error key if the value does not match the
- * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
- * patterns defined as scope expressions.
- *
- * @example
- <doc:example>
- <doc:source>
- <script>
- function Ctrl($scope) {
- $scope.text = 'me@example.com';
- }
- </script>
+ /**
+ * @ngdoc inputType
+ * @name angular.module.ng.$compileProvider.directive.input.text
+ *
+ * @description
+ * Standard HTML text input with angular data binding.
+ *
+ * @param {string} ng:model Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the widgets is published.
+ * @param {string=} required Sets `REQUIRED` validation error key if the value is not entered.
+ * @param {number=} ng:minlength Sets `MINLENGTH` validation error key if the value is shorter than
+ * minlength.
+ * @param {number=} ng:maxlength Sets `MAXLENGTH` validation error key if the value is longer than
+ * maxlength.
+ * @param {string=} ng:pattern Sets `PATTERN` validation error key if the value does not match the
+ * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
+ * patterns defined as scope expressions.
+ * @param {string=} ng:change Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ *
+ * @example
+ <doc:example>
+ <doc:source>
+ <script>
+ function Ctrl($scope) {
+ $scope.text = 'guest';
+ $scope.word = /^\w*$/;
+ }
+ </script>
<form name="myForm" ng:controller="Ctrl">
- Email: <input type="email" name="input" ng:model="text" required>
+ Single word: <input type="text" name="input" ng:model="text"
+ ng:pattern="word" required>
<span class="error" ng:show="myForm.input.error.REQUIRED">
Required!</span>
- <span class="error" ng:show="myForm.input.error.EMAIL">
- Not valid email!</span>
+ <span class="error" ng:show="myForm.input.error.PATTERN">
+ Single word only!</span>
+
<tt>text = {{text}}</tt><br/>
<tt>myForm.input.valid = {{myForm.input.valid}}</tt><br/>
<tt>myForm.input.error = {{myForm.input.error}}</tt><br/>
<tt>myForm.valid = {{myForm.valid}}</tt><br/>
<tt>myForm.error.REQUIRED = {{!!myForm.error.REQUIRED}}</tt><br/>
- <tt>myForm.error.EMAIL = {{!!myForm.error.EMAIL}}</tt><br/>
- </form>
- </doc:source>
- <doc:scenario>
- it('should initialize to model', function() {
- expect(binding('text')).toEqual('me@example.com');
- expect(binding('myForm.input.valid')).toEqual('true');
- });
-
- it('should be invalid if empty', function() {
- input('text').enter('');
- expect(binding('text')).toEqual('');
- expect(binding('myForm.input.valid')).toEqual('false');
- });
-
- it('should be invalid if not email', function() {
- input('text').enter('xxx');
- expect(binding('myForm.input.valid')).toEqual('false');
- });
- </doc:scenario>
- </doc:example>
- */
-
-
-/**
- * @ngdoc inputType
- * @name angular.inputType.url
- *
- * @description
- * Text input with URL validation. Sets the `URL` validation error key if the content is not a
- * valid URL.
- *
- * @param {string} ng:model Assignable angular expression to data-bind to.
- * @param {string=} name Property name of the form under which the widgets is published.
- * @param {string=} required Sets `REQUIRED` validation error key if the value is not entered.
- * @param {number=} ng:minlength Sets `MINLENGTH` validation error key if the value is shorter than
- * minlength.
- * @param {number=} ng:maxlength Sets `MAXLENGTH` validation error key if the value is longer than
- * maxlength.
- * @param {string=} ng:pattern Sets `PATTERN` validation error key if the value does not match the
- * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
- * patterns defined as scope expressions.
- * @param {string=} ng:change Angular expression to be executed when input changes due to user
- * interaction with the input element.
- *
- * @example
- <doc:example>
- <doc:source>
- <script>
- function Ctrl($scope) {
- $scope.text = 'http://google.com';
- }
- </script>
- <form name="myForm" ng:controller="Ctrl">
- URL: <input type="url" name="input" ng:model="text" required>
- <span class="error" ng:show="myForm.input.error.REQUIRED">
- Required!</span>
- <span class="error" ng:show="myForm.input.error.url">
- Not valid url!</span>
- <tt>text = {{text}}</tt><br/>
- <tt>myForm.input.valid = {{myForm.input.valid}}</tt><br/>
- <tt>myForm.input.error = {{myForm.input.error}}</tt><br/>
- <tt>myForm.valid = {{myForm.valid}}</tt><br/>
- <tt>myForm.error.REQUIRED = {{!!myForm.error.REQUIRED}}</tt><br/>
- <tt>myForm.error.url = {{!!myForm.error.url}}</tt><br/>
- </form>
- </doc:source>
- <doc:scenario>
- it('should initialize to model', function() {
- expect(binding('text')).toEqual('http://google.com');
- expect(binding('myForm.input.valid')).toEqual('true');
- });
-
- it('should be invalid if empty', function() {
- input('text').enter('');
- expect(binding('text')).toEqual('');
- expect(binding('myForm.input.valid')).toEqual('false');
- });
-
- it('should be invalid if not url', function() {
- input('text').enter('xxx');
- expect(binding('myForm.input.valid')).toEqual('false');
- });
- </doc:scenario>
- </doc:example>
- */
-
-
-/**
- * @ngdoc inputType
- * @name angular.inputType.list
- *
- * @description
- * Text input that converts between comma-seperated string into an array of strings.
- *
- * @param {string} ng:model Assignable angular expression to data-bind to.
- * @param {string=} name Property name of the form under which the widgets is published.
- * @param {string=} required Sets `REQUIRED` validation error key if the value is not entered.
- * @param {string=} ng:pattern Sets `PATTERN` validation error key if the value does not match the
- * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
- * patterns defined as scope expressions.
- * @param {string=} ng:change Angular expression to be executed when input changes due to user
- * interaction with the input element.
- *
- * @example
- <doc:example>
- <doc:source>
- <script>
- function Ctrl($scope) {
- $scope.names = ['igor', 'misko', 'vojta'];
- }
- </script>
- <form name="myForm" ng:controller="Ctrl">
- List: <input type="list" name="input" ng:model="names" required>
- <span class="error" ng:show="myForm.list.error.REQUIRED">
- Required!</span>
- <tt>names = {{names}}</tt><br/>
- <tt>myForm.input.valid = {{myForm.input.valid}}</tt><br/>
- <tt>myForm.input.error = {{myForm.input.error}}</tt><br/>
- <tt>myForm.valid = {{myForm.valid}}</tt><br/>
- <tt>myForm.error.REQUIRED = {{!!myForm.error.REQUIRED}}</tt><br/>
- </form>
- </doc:source>
- <doc:scenario>
- it('should initialize to model', function() {
- expect(binding('names')).toEqual('["igor","misko","vojta"]');
- expect(binding('myForm.input.valid')).toEqual('true');
- });
-
- it('should be invalid if empty', function() {
- input('names').enter('');
- expect(binding('names')).toEqual('');
- expect(binding('myForm.input.valid')).toEqual('false');
- });
- </doc:scenario>
- </doc:example>
- */
-var ngListDirective = function() {
- return {
- require: 'ngModel',
- link: function(scope, element, attr, ctrl) {
- var parse = function(viewValue) {
- var list = [];
-
- if (viewValue) {
- forEach(viewValue.split(/\s*,\s*/), function(value) {
- if (value) list.push(value);
+ </form>
+ </doc:source>
+ <doc:scenario>
+ it('should initialize to model', function() {
+ expect(binding('text')).toEqual('guest');
+ expect(binding('myForm.input.valid')).toEqual('true');
});
- }
-
- return list;
- };
- ctrl.parsers.push(parse);
- ctrl.formatters.push(function(value) {
- if (isArray(value) && !equals(parse(ctrl.viewValue), value)) {
- return value.join(', ');
- }
-
- return undefined;
- });
- }
- };
-};
+ it('should be invalid if empty', function() {
+ input('text').enter('');
+ expect(binding('text')).toEqual('');
+ expect(binding('myForm.input.valid')).toEqual('false');
+ });
-/**
- * @ngdoc inputType
- * @name angular.inputType.number
- *
- * @description
- * Text input with number validation and transformation. Sets the `NUMBER` validation
- * error if not a valid number.
- *
- * @param {string} ng:model Assignable angular expression to data-bind to.
- * @param {string=} name Property name of the form under which the widgets is published.
- * @param {string=} min Sets the `MIN` validation error key if the value entered is less then `min`.
- * @param {string=} max Sets the `MAX` validation error key if the value entered is greater then `min`.
- * @param {string=} required Sets `REQUIRED` validation error key if the value is not entered.
- * @param {number=} ng:minlength Sets `MINLENGTH` validation error key if the value is shorter than
- * minlength.
- * @param {number=} ng:maxlength Sets `MAXLENGTH` validation error key if the value is longer than
- * maxlength.
- * @param {string=} ng:pattern Sets `PATTERN` validation error key if the value does not match the
- * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
- * patterns defined as scope expressions.
- * @param {string=} ng:change Angular expression to be executed when input changes due to user
- * interaction with the input element.
- *
- * @example
- <doc:example>
- <doc:source>
- <script>
- function Ctrl($scope) {
- $scope.value = 12;
- }
- </script>
- <form name="myForm" ng:controller="Ctrl">
- Number: <input type="number" name="input" ng:model="value"
- min="0" max="99" required>
- <span class="error" ng:show="myForm.list.error.REQUIRED">
- Required!</span>
- <span class="error" ng:show="myForm.list.error.NUMBER">
- Not valid number!</span>
- <tt>value = {{value}}</tt><br/>
- <tt>myForm.input.valid = {{myForm.input.valid}}</tt><br/>
- <tt>myForm.input.error = {{myForm.input.error}}</tt><br/>
- <tt>myForm.valid = {{myForm.valid}}</tt><br/>
- <tt>myForm.error.REQUIRED = {{!!myForm.error.REQUIRED}}</tt><br/>
- </form>
- </doc:source>
- <doc:scenario>
- it('should initialize to model', function() {
- expect(binding('value')).toEqual('12');
- expect(binding('myForm.input.valid')).toEqual('true');
- });
+ it('should be invalid if multi word', function() {
+ input('text').enter('hello world');
+ expect(binding('myForm.input.valid')).toEqual('false');
+ });
+ </doc:scenario>
+ </doc:example>
+ */
+ 'text': textInputType,
- it('should be invalid if empty', function() {
- input('value').enter('');
- expect(binding('value')).toEqual('');
- expect(binding('myForm.input.valid')).toEqual('false');
- });
- it('should be invalid if over max', function() {
- input('value').enter('123');
- expect(binding('value')).toEqual('12');
- expect(binding('myForm.input.valid')).toEqual('false');
- });
- </doc:scenario>
- </doc:example>
- */
+ /**
+ * @ngdoc inputType
+ * @name angular.module.ng.$compileProvider.directive.input.number
+ *
+ * @description
+ * Text input with number validation and transformation. Sets the `NUMBER` validation
+ * error if not a valid number.
+ *
+ * @param {string} ng:model Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the widgets is published.
+ * @param {string=} min Sets the `MIN` validation error key if the value entered is less then `min`.
+ * @param {string=} max Sets the `MAX` validation error key if the value entered is greater then `min`.
+ * @param {string=} required Sets `REQUIRED` validation error key if the value is not entered.
+ * @param {number=} ng:minlength Sets `MINLENGTH` validation error key if the value is shorter than
+ * minlength.
+ * @param {number=} ng:maxlength Sets `MAXLENGTH` validation error key if the value is longer than
+ * maxlength.
+ * @param {string=} ng:pattern Sets `PATTERN` validation error key if the value does not match the
+ * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
+ * patterns defined as scope expressions.
+ * @param {string=} ng:change Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ *
+ * @example
+ <doc:example>
+ <doc:source>
+ <script>
+ function Ctrl($scope) {
+ $scope.value = 12;
+ }
+ </script>
+ <form name="myForm" ng:controller="Ctrl">
+ Number: <input type="number" name="input" ng:model="value"
+ min="0" max="99" required>
+ <span class="error" ng:show="myForm.list.error.REQUIRED">
+ Required!</span>
+ <span class="error" ng:show="myForm.list.error.NUMBER">
+ Not valid number!</span>
+ <tt>value = {{value}}</tt><br/>
+ <tt>myForm.input.valid = {{myForm.input.valid}}</tt><br/>
+ <tt>myForm.input.error = {{myForm.input.error}}</tt><br/>
+ <tt>myForm.valid = {{myForm.valid}}</tt><br/>
+ <tt>myForm.error.REQUIRED = {{!!myForm.error.REQUIRED}}</tt><br/>
+ </form>
+ </doc:source>
+ <doc:scenario>
+ it('should initialize to model', function() {
+ expect(binding('value')).toEqual('12');
+ expect(binding('myForm.input.valid')).toEqual('true');
+ });
+ it('should be invalid if empty', function() {
+ input('value').enter('');
+ expect(binding('value')).toEqual('');
+ expect(binding('myForm.input.valid')).toEqual('false');
+ });
-/**
- * @ngdoc inputType
- * @name angular.inputType.checkbox
- *
- * @description
- * HTML checkbox.
- *
- * @param {string} ng:model Assignable angular expression to data-bind to.
- * @param {string=} name Property name of the form under which the widgets is published.
- * @param {string=} ng:true-value The value to which the expression should be set when selected.
- * @param {string=} ng:false-value The value to which the expression should be set when not selected.
- * @param {string=} ng:change Angular expression to be executed when input changes due to user
- * interaction with the input element.
- *
- * @example
- <doc:example>
- <doc:source>
- <script>
- function Ctrl($scope) {
- $scope.value1 = true;
- $scope.value2 = 'YES'
- }
- </script>
- <form name="myForm" ng:controller="Ctrl">
- Value1: <input type="checkbox" ng:model="value1"> <br/>
- Value2: <input type="checkbox" ng:model="value2"
- ng:true-value="YES" ng:false-value="NO"> <br/>
- <tt>value1 = {{value1}}</tt><br/>
- <tt>value2 = {{value2}}</tt><br/>
- </form>
- </doc:source>
- <doc:scenario>
- it('should change state', function() {
- expect(binding('value1')).toEqual('true');
- expect(binding('value2')).toEqual('YES');
-
- input('value1').check();
- input('value2').check();
- expect(binding('value1')).toEqual('false');
- expect(binding('value2')).toEqual('NO');
- });
- </doc:scenario>
- </doc:example>
- */
+ it('should be invalid if over max', function() {
+ input('value').enter('123');
+ expect(binding('value')).toEqual('12');
+ expect(binding('myForm.input.valid')).toEqual('false');
+ });
+ </doc:scenario>
+ </doc:example>
+ */
+ 'number': numberInputType,
+ /**
+ * @ngdoc inputType
+ * @name angular.module.ng.$compileProvider.directive.input.url
+ *
+ * @description
+ * Text input with URL validation. Sets the `URL` validation error key if the content is not a
+ * valid URL.
+ *
+ * @param {string} ng:model Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the widgets is published.
+ * @param {string=} required Sets `REQUIRED` validation error key if the value is not entered.
+ * @param {number=} ng:minlength Sets `MINLENGTH` validation error key if the value is shorter than
+ * minlength.
+ * @param {number=} ng:maxlength Sets `MAXLENGTH` validation error key if the value is longer than
+ * maxlength.
+ * @param {string=} ng:pattern Sets `PATTERN` validation error key if the value does not match the
+ * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
+ * patterns defined as scope expressions.
+ * @param {string=} ng:change Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ *
+ * @example
+ <doc:example>
+ <doc:source>
+ <script>
+ function Ctrl($scope) {
+ $scope.text = 'http://google.com';
+ }
+ </script>
+ <form name="myForm" ng:controller="Ctrl">
+ URL: <input type="url" name="input" ng:model="text" required>
+ <span class="error" ng:show="myForm.input.error.REQUIRED">
+ Required!</span>
+ <span class="error" ng:show="myForm.input.error.url">
+ Not valid url!</span>
+ <tt>text = {{text}}</tt><br/>
+ <tt>myForm.input.valid = {{myForm.input.valid}}</tt><br/>
+ <tt>myForm.input.error = {{myForm.input.error}}</tt><br/>
+ <tt>myForm.valid = {{myForm.valid}}</tt><br/>
+ <tt>myForm.error.REQUIRED = {{!!myForm.error.REQUIRED}}</tt><br/>
+ <tt>myForm.error.url = {{!!myForm.error.url}}</tt><br/>
+ </form>
+ </doc:source>
+ <doc:scenario>
+ it('should initialize to model', function() {
+ expect(binding('text')).toEqual('http://google.com');
+ expect(binding('myForm.input.valid')).toEqual('true');
+ });
-/**
- * @ngdoc inputType
- * @name angular.inputType.radio
- *
- * @description
- * HTML radio button.
- *
- * @param {string} ng:model Assignable angular expression to data-bind to.
- * @param {string} value The value to which the expression should be set when selected.
- * @param {string=} name Property name of the form under which the widgets is published.
- * @param {string=} ng:change Angular expression to be executed when input changes due to user
- * interaction with the input element.
- *
- * @example
- <doc:example>
- <doc:source>
- <script>
- function Ctrl($scope) {
- $scope.color = 'blue';
- }
- </script>
- <form name="myForm" ng:controller="Ctrl">
- <input type="radio" ng:model="color" value="red"> Red <br/>
- <input type="radio" ng:model="color" value="green"> Green <br/>
- <input type="radio" ng:model="color" value="blue"> Blue <br/>
- <tt>color = {{color}}</tt><br/>
- </form>
- </doc:source>
- <doc:scenario>
- it('should change state', function() {
- expect(binding('color')).toEqual('blue');
+ it('should be invalid if empty', function() {
+ input('text').enter('');
+ expect(binding('text')).toEqual('');
+ expect(binding('myForm.input.valid')).toEqual('false');
+ });
- input('color').select('red');
- expect(binding('color')).toEqual('red');
- });
- </doc:scenario>
- </doc:example>
- */
+ it('should be invalid if not url', function() {
+ input('text').enter('xxx');
+ expect(binding('myForm.input.valid')).toEqual('false');
+ });
+ </doc:scenario>
+ </doc:example>
+ */
+ 'url': urlInputType,
-/**
- * @ngdoc widget
- * @name angular.module.ng.$compileProvider.directive.input
- *
- * @description
- * HTML input element widget with angular data-binding. Input widget follows HTML5 input types
- * and polyfills the HTML5 validation behavior for older browsers.
- *
- * The {@link angular.inputType custom angular.inputType}s provide a shorthand for declaring new
- * inputs. This is a sharthand for text-box based inputs, and there is no need to go through the
- * full {@link angular.module.ng.$formFactory $formFactory} widget lifecycle.
- *
- *
- * @param {string} type Widget types as defined by {@link angular.inputType}. If the
- * type is in the format of `@ScopeType` then `ScopeType` is loaded from the
- * current scope, allowing quick definition of type.
- * @param {string} ng:model Assignable angular expression to data-bind to.
- * @param {string=} name Property name of the form under which the widgets is published.
- * @param {string=} required Sets `REQUIRED` validation error key if the value is not entered.
- * @param {number=} ng:minlength Sets `MINLENGTH` validation error key if the value is shorter than
- * minlength.
- * @param {number=} ng:maxlength Sets `MAXLENGTH` validation error key if the value is longer than
- * maxlength.
- * @param {string=} ng:pattern Sets `PATTERN` validation error key if the value does not match the
- * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
- * patterns defined as scope expressions.
- * @param {string=} ng:change Angular expression to be executed when input changes due to user
- * interaction with the input element.
- *
- * @example
- <doc:example>
- <doc:source>
- <script>
- function Ctrl($scope) {
- $scope.user = {name: 'guest', last: 'visitor'};
- }
- </script>
- <div ng:controller="Ctrl">
- <form name="myForm">
- User name: <input type="text" name="userName" ng:model="user.name" required>
- <span class="error" ng:show="myForm.userName.error.REQUIRED">
- Required!</span><br>
- Last name: <input type="text" name="lastName" ng:model="user.last"
- ng:minlength="3" ng:maxlength="10">
- <span class="error" ng:show="myForm.lastName.error.MINLENGTH">
- Too short!</span>
- <span class="error" ng:show="myForm.lastName.error.MAXLENGTH">
- Too long!</span><br>
- </form>
- <hr>
- <tt>user = {{user}}</tt><br/>
- <tt>myForm.userName.valid = {{myForm.userName.valid}}</tt><br>
- <tt>myForm.userName.error = {{myForm.userName.error}}</tt><br>
- <tt>myForm.lastName.valid = {{myForm.lastName.valid}}</tt><br>
- <tt>myForm.userName.error = {{myForm.lastName.error}}</tt><br>
- <tt>myForm.valid = {{myForm.valid}}</tt><br>
- <tt>myForm.error.REQUIRED = {{!!myForm.error.REQUIRED}}</tt><br>
- <tt>myForm.error.MINLENGTH = {{!!myForm.error.MINLENGTH}}</tt><br>
- <tt>myForm.error.MAXLENGTH = {{!!myForm.error.MAXLENGTH}}</tt><br>
- </div>
- </doc:source>
- <doc:scenario>
- it('should initialize to model', function() {
- expect(binding('user')).toEqual('{"last":"visitor","name":"guest"}');
- expect(binding('myForm.userName.valid')).toEqual('true');
- expect(binding('myForm.valid')).toEqual('true');
- });
+ /**
+ * @ngdoc inputType
+ * @name angular.module.ng.$compileProvider.directive.input.email
+ *
+ * @description
+ * Text input with email validation. Sets the `EMAIL` validation error key if not a valid email
+ * address.
+ *
+ * @param {string} ng:model Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the widgets is published.
+ * @param {string=} required Sets `REQUIRED` validation error key if the value is not entered.
+ * @param {number=} ng:minlength Sets `MINLENGTH` validation error key if the value is shorter than
+ * minlength.
+ * @param {number=} ng:maxlength Sets `MAXLENGTH` validation error key if the value is longer than
+ * maxlength.
+ * @param {string=} ng:pattern Sets `PATTERN` validation error key if the value does not match the
+ * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
+ * patterns defined as scope expressions.
+ *
+ * @example
+ <doc:example>
+ <doc:source>
+ <script>
+ function Ctrl($scope) {
+ $scope.text = 'me@example.com';
+ }
+ </script>
+ <form name="myForm" ng:controller="Ctrl">
+ Email: <input type="email" name="input" ng:model="text" required>
+ <span class="error" ng:show="myForm.input.error.REQUIRED">
+ Required!</span>
+ <span class="error" ng:show="myForm.input.error.EMAIL">
+ Not valid email!</span>
+ <tt>text = {{text}}</tt><br/>
+ <tt>myForm.input.valid = {{myForm.input.valid}}</tt><br/>
+ <tt>myForm.input.error = {{myForm.input.error}}</tt><br/>
+ <tt>myForm.valid = {{myForm.valid}}</tt><br/>
+ <tt>myForm.error.REQUIRED = {{!!myForm.error.REQUIRED}}</tt><br/>
+ <tt>myForm.error.EMAIL = {{!!myForm.error.EMAIL}}</tt><br/>
+ </form>
+ </doc:source>
+ <doc:scenario>
+ it('should initialize to model', function() {
+ expect(binding('text')).toEqual('me@example.com');
+ expect(binding('myForm.input.valid')).toEqual('true');
+ });
- it('should be invalid if empty when required', function() {
- input('user.name').enter('');
- expect(binding('user')).toEqual('{"last":"visitor","name":null}');
- expect(binding('myForm.userName.valid')).toEqual('false');
- expect(binding('myForm.valid')).toEqual('false');
- });
+ it('should be invalid if empty', function() {
+ input('text').enter('');
+ expect(binding('text')).toEqual('');
+ expect(binding('myForm.input.valid')).toEqual('false');
+ });
- it('should be valid if empty when min length is set', function() {
- input('user.last').enter('');
- expect(binding('user')).toEqual('{"last":"","name":"guest"}');
- expect(binding('myForm.lastName.valid')).toEqual('true');
- expect(binding('myForm.valid')).toEqual('true');
- });
+ it('should be invalid if not email', function() {
+ input('text').enter('xxx');
+ expect(binding('myForm.input.valid')).toEqual('false');
+ });
+ </doc:scenario>
+ </doc:example>
+ */
+ 'email': emailInputType,
- it('should be invalid if less than required min length', function() {
- input('user.last').enter('xx');
- expect(binding('user')).toEqual('{"last":"visitor","name":"guest"}');
- expect(binding('myForm.lastName.valid')).toEqual('false');
- expect(binding('myForm.lastName.error')).toMatch(/MINLENGTH/);
- expect(binding('myForm.valid')).toEqual('false');
- });
- it('should be valid if longer than max length', function() {
- input('user.last').enter('some ridiculously long name');
- expect(binding('user'))
- .toEqual('{"last":"visitor","name":"guest"}');
- expect(binding('myForm.lastName.valid')).toEqual('false');
- expect(binding('myForm.lastName.error')).toMatch(/MAXLENGTH/);
- expect(binding('myForm.valid')).toEqual('false');
- });
- </doc:scenario>
- </doc:example>
- */
+ /**
+ * @ngdoc inputType
+ * @name angular.module.ng.$compileProvider.directive.input.radio
+ *
+ * @description
+ * HTML radio button.
+ *
+ * @param {string} ng:model Assignable angular expression to data-bind to.
+ * @param {string} value The value to which the expression should be set when selected.
+ * @param {string=} name Property name of the form under which the widgets is published.
+ * @param {string=} ng:change Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ *
+ * @example
+ <doc:example>
+ <doc:source>
+ <script>
+ function Ctrl($scope) {
+ $scope.color = 'blue';
+ }
+ </script>
+ <form name="myForm" ng:controller="Ctrl">
+ <input type="radio" ng:model="color" value="red"> Red <br/>
+ <input type="radio" ng:model="color" value="green"> Green <br/>
+ <input type="radio" ng:model="color" value="blue"> Blue <br/>
+ <tt>color = {{color}}</tt><br/>
+ </form>
+ </doc:source>
+ <doc:scenario>
+ it('should change state', function() {
+ expect(binding('color')).toEqual('blue');
+
+ input('color').select('red');
+ expect(binding('color')).toEqual('red');
+ });
+ </doc:scenario>
+ </doc:example>
+ */
+ 'radio': radioInputType,
-/**
- * @ngdoc widget
- * @name angular.module.ng.$compileProvider.directive.textarea
- *
- * @description
- * HTML textarea element widget with angular data-binding. The data-binding and validation
- * properties of this element are exactly the same as those of the
- * {@link angular.module.ng.$compileProvider.directive.input input element}.
- *
- * @param {string} type Widget types as defined by {@link angular.inputType}. If the
- * type is in the format of `@ScopeType` then `ScopeType` is loaded from the
- * current scope, allowing quick definition of type.
- * @param {string} ng:model Assignable angular expression to data-bind to.
- * @param {string=} name Property name of the form under which the widgets is published.
- * @param {string=} required Sets `REQUIRED` validation error key if the value is not entered.
- * @param {number=} ng:minlength Sets `MINLENGTH` validation error key if the value is shorter than
- * minlength.
- * @param {number=} ng:maxlength Sets `MAXLENGTH` validation error key if the value is longer than
- * maxlength.
- * @param {string=} ng:pattern Sets `PATTERN` validation error key if the value does not match the
- * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
- * patterns defined as scope expressions.
- * @param {string=} ng:change Angular expression to be executed when input changes due to user
- * interaction with the input element.
- */
-var inputType = {
- 'text': textInputType,
- 'number': numberInputType,
- 'url': urlInputType,
- 'email': emailInputType,
-
- 'radio': radioInputType,
+ /**
+ * @ngdoc inputType
+ * @name angular.module.ng.$compileProvider.directive.input.checkbox
+ *
+ * @description
+ * HTML checkbox.
+ *
+ * @param {string} ng:model Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the widgets is published.
+ * @param {string=} ng:true-value The value to which the expression should be set when selected.
+ * @param {string=} ng:false-value The value to which the expression should be set when not selected.
+ * @param {string=} ng:change Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ *
+ * @example
+ <doc:example>
+ <doc:source>
+ <script>
+ function Ctrl($scope) {
+ $scope.value1 = true;
+ $scope.value2 = 'YES'
+ }
+ </script>
+ <form name="myForm" ng:controller="Ctrl">
+ Value1: <input type="checkbox" ng:model="value1"> <br/>
+ Value2: <input type="checkbox" ng:model="value2"
+ ng:true-value="YES" ng:false-value="NO"> <br/>
+ <tt>value1 = {{value1}}</tt><br/>
+ <tt>value2 = {{value2}}</tt><br/>
+ </form>
+ </doc:source>
+ <doc:scenario>
+ it('should change state', function() {
+ expect(binding('value1')).toEqual('true');
+ expect(binding('value2')).toEqual('YES');
+
+ input('value1').check();
+ input('value2').check();
+ expect(binding('value1')).toEqual('false');
+ expect(binding('value2')).toEqual('NO');
+ });
+ </doc:scenario>
+ </doc:example>
+ */
'checkbox': checkboxInputType,
'hidden': noop,
@@ -808,6 +598,123 @@ function checkboxInputType(scope, element, attr, ctrl) {
}
+/**
+ * @ngdoc widget
+ * @name angular.module.ng.$compileProvider.directive.textarea
+ *
+ * @description
+ * HTML textarea element widget with angular data-binding. The data-binding and validation
+ * properties of this element are exactly the same as those of the
+ * {@link angular.module.ng.$compileProvider.directive.input input element}.
+ *
+ * @param {string} ng:model Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the widgets is published.
+ * @param {string=} required Sets `REQUIRED` validation error key if the value is not entered.
+ * @param {number=} ng:minlength Sets `MINLENGTH` validation error key if the value is shorter than
+ * minlength.
+ * @param {number=} ng:maxlength Sets `MAXLENGTH` validation error key if the value is longer than
+ * maxlength.
+ * @param {string=} ng:pattern Sets `PATTERN` validation error key if the value does not match the
+ * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
+ * patterns defined as scope expressions.
+ * @param {string=} ng:change Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ */
+
+
+/**
+ * @ngdoc widget
+ * @name angular.module.ng.$compileProvider.directive.input
+ *
+ * @description
+ * HTML input element widget with angular data-binding. Input widget follows HTML5 input types
+ * and polyfills the HTML5 validation behavior for older browsers.
+ *
+ * @param {string} ng:model Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the widgets is published.
+ * @param {string=} required Sets `REQUIRED` validation error key if the value is not entered.
+ * @param {number=} ng:minlength Sets `MINLENGTH` validation error key if the value is shorter than
+ * minlength.
+ * @param {number=} ng:maxlength Sets `MAXLENGTH` validation error key if the value is longer than
+ * maxlength.
+ * @param {string=} ng:pattern Sets `PATTERN` validation error key if the value does not match the
+ * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
+ * patterns defined as scope expressions.
+ * @param {string=} ng:change Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ *
+ * @example
+ <doc:example>
+ <doc:source>
+ <script>
+ function Ctrl($scope) {
+ $scope.user = {name: 'guest', last: 'visitor'};
+ }
+ </script>
+ <div ng:controller="Ctrl">
+ <form name="myForm">
+ User name: <input type="text" name="userName" ng:model="user.name" required>
+ <span class="error" ng:show="myForm.userName.error.REQUIRED">
+ Required!</span><br>
+ Last name: <input type="text" name="lastName" ng:model="user.last"
+ ng:minlength="3" ng:maxlength="10">
+ <span class="error" ng:show="myForm.lastName.error.MINLENGTH">
+ Too short!</span>
+ <span class="error" ng:show="myForm.lastName.error.MAXLENGTH">
+ Too long!</span><br>
+ </form>
+ <hr>
+ <tt>user = {{user}}</tt><br/>
+ <tt>myForm.userName.valid = {{myForm.userName.valid}}</tt><br>
+ <tt>myForm.userName.error = {{myForm.userName.error}}</tt><br>
+ <tt>myForm.lastName.valid = {{myForm.lastName.valid}}</tt><br>
+ <tt>myForm.userName.error = {{myForm.lastName.error}}</tt><br>
+ <tt>myForm.valid = {{myForm.valid}}</tt><br>
+ <tt>myForm.error.REQUIRED = {{!!myForm.error.REQUIRED}}</tt><br>
+ <tt>myForm.error.MINLENGTH = {{!!myForm.error.MINLENGTH}}</tt><br>
+ <tt>myForm.error.MAXLENGTH = {{!!myForm.error.MAXLENGTH}}</tt><br>
+ </div>
+ </doc:source>
+ <doc:scenario>
+ it('should initialize to model', function() {
+ expect(binding('user')).toEqual('{"last":"visitor","name":"guest"}');
+ expect(binding('myForm.userName.valid')).toEqual('true');
+ expect(binding('myForm.valid')).toEqual('true');
+ });
+
+ it('should be invalid if empty when required', function() {
+ input('user.name').enter('');
+ expect(binding('user')).toEqual('{"last":"visitor","name":null}');
+ expect(binding('myForm.userName.valid')).toEqual('false');
+ expect(binding('myForm.valid')).toEqual('false');
+ });
+
+ it('should be valid if empty when min length is set', function() {
+ input('user.last').enter('');
+ expect(binding('user')).toEqual('{"last":"","name":"guest"}');
+ expect(binding('myForm.lastName.valid')).toEqual('true');
+ expect(binding('myForm.valid')).toEqual('true');
+ });
+
+ it('should be invalid if less than required min length', function() {
+ input('user.last').enter('xx');
+ expect(binding('user')).toEqual('{"last":"visitor","name":"guest"}');
+ expect(binding('myForm.lastName.valid')).toEqual('false');
+ expect(binding('myForm.lastName.error')).toMatch(/MINLENGTH/);
+ expect(binding('myForm.valid')).toEqual('false');
+ });
+
+ it('should be valid if longer than max length', function() {
+ input('user.last').enter('some ridiculously long name');
+ expect(binding('user'))
+ .toEqual('{"last":"visitor","name":"guest"}');
+ expect(binding('myForm.lastName.valid')).toEqual('false');
+ expect(binding('myForm.lastName.error')).toMatch(/MAXLENGTH/);
+ expect(binding('myForm.valid')).toEqual('false');
+ });
+ </doc:scenario>
+ </doc:example>
+ */
var inputDirective = [function() {
return {
restrict: 'E',
@@ -821,6 +728,28 @@ var inputDirective = [function() {
}];
+/**
+ * @ngdoc object
+ * @name angular.module.ng.$compileProvider.directive.ng:model.NgModelController
+ *
+ * @property {string} viewValue Actual string value in the view.
+ * @property {*} modelValue The value in the model, that the widget is bound to.
+ * @property {Array.<Function>} parsers Whenever the widget reads value from the DOM, it executes
+ * all of these functions to sanitize / convert the value as well as validate.
+ *
+ * @property {Array.<Function>} formatters Wheneveer the model value changes, it executes all of
+ * these functions to convert the value as well as validate.
+ *
+ * @property {Object} error An bject hash with all errors as keys.
+ *
+ * @property {boolean} pristine True if user has not interacted with the widget yet.
+ * @property {boolean} dirty True if user has already interacted with the widget.
+ * @property {boolean} valid True if there is no error.
+ * @property {boolean} invalid True if at least one error on the widget.
+ *
+ * @description
+ *
+ */
var NgModelController = ['$scope', '$exceptionHandler', 'ngModel',
function($scope, $exceptionHandler, ngModel) {
this.viewValue = Number.NaN;
@@ -834,6 +763,21 @@ var NgModelController = ['$scope', '$exceptionHandler', 'ngModel',
this.invalid = false;
this.render = noop;
+
+ /**
+ * @ngdoc function
+ * @name angular.module.ng.$compileProvider.directive.ng:model.NgModelController#touch
+ * @methodOf angular.module.ng.$compileProvider.directive.ng:model.NgModelController
+ *
+ * @return {boolean} Whether it did change state.
+ *
+ * @description
+ * This method should be called from within a DOM event handler.
+ * For example {@link angular.module.ng.$compileProvider.directive.input input} or
+ * {@link angular.module.ng.$compileProvider.directive.select select} directives call it.
+ *
+ * It changes state to `dirty` and emits `$viewTouch` event if the state was `pristine` before.
+ */
this.touch = function() {
if (this.dirty) return false;
@@ -847,31 +791,59 @@ var NgModelController = ['$scope', '$exceptionHandler', 'ngModel',
return true;
};
- // don't $emit valid if already valid, the same for $invalid
- // not sure about this method name, should the argument be reversed ? emitError ?
+
+ /**
+ * @ngdoc function
+ * @name angular.module.ng.$compileProvider.directive.ng:model.NgModelController#emitValidity
+ * @methodOf angular.module.ng.$compileProvider.directive.ng:model.NgModelController
+ *
+ * @description
+ * Change the validity state, and notifies the form when the widget changes validity. (i.e. does
+ * not emit `$invalid` if given validator is already marked as invalid).
+ *
+ * This method should be called by validators - ie the parser or formatter method.
+ *
+ * @param {string} name Name of the validator.
+ * @param {boolean} isValid Whether it should $emit `$valid` (true) or `$invalid` (false) event.
+ */
this.emitValidity = function(name, isValid) {
if (!isValid && this.error[name]) return;
if (isValid && !this.error[name]) return;
- if (!isValid) {
- this.error[name] = true;
- this.invalid = true;
- this.valid = false;
- }
-
if (isValid) {
delete this.error[name];
if (equals(this.error, {})) {
this.valid = true;
this.invalid = false;
}
+ } else {
+ this.error[name] = true;
+ this.invalid = true;
+ this.valid = false;
}
return $scope.$emit(isValid ? '$valid' : '$invalid', name, this);
};
- // view -> model
+
+ /**
+ * @ngdoc function
+ * @name angular.module.ng.$compileProvider.directive.ng:model.NgModelController#read
+ * @methodOf angular.module.ng.$compileProvider.directive.ng:model.NgModelController
+ *
+ * @description
+ * Read a value from view.
+ *
+ * This method should be called from within a DOM event handler.
+ * For example {@link angular.module.ng.$compileProvider.directive.input input} or
+ * {@link angular.module.ng.$compileProvider.directive.select select} directives call it.
+ *
+ * It internally calls all `formatters` and if resulted value is valid, update the model and emits
+ * `$viewChange` event afterwards.
+ *
+ * @param {string} value Value from the view
+ */
this.read = function(value) {
this.viewValue = value;
@@ -911,6 +883,37 @@ var NgModelController = ['$scope', '$exceptionHandler', 'ngModel',
}];
+/**
+ * @ngdoc directive
+ * @name angular.module.ng.$compileProvider.directive.ng:model
+ *
+ * @element input
+ *
+ * @description
+ * Is directive that tells Angular to do two-way data binding. It works together with `input`, `select`, `textarea`. You can easily write your own directives to use `ng:model` pretty easily.
+ *
+ * `ng:model` is responsible for:
+ *
+ * - binding the view into the model, which other directives such as `input`, `textarea` or `select`
+ * require,
+ * - providing validation behavior (i.e. required, number, email, url),
+ * - keeping state of the widget (valid/invalid, dirty/pristine, validation errors),
+ * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`),
+ * - register the widget with parent {@link angular.module.ng.$compileProvider.directive.form form}.
+ *
+ * For examples, how to use `ng:model`, see:
+ *
+ * - {@link angular.module.ng.$compileProvider.directive.input input}
+ * - {@link angular.module.ng.$compileProvider.directive.input.text text}
+ * - {@link angular.module.ng.$compileProvider.directive.input.checkbox checkbox}
+ * - {@link angular.module.ng.$compileProvider.directive.input.radio radio}
+ * - {@link angular.module.ng.$compileProvider.directive.input.number number}
+ * - {@link angular.module.ng.$compileProvider.directive.input.email email}
+ * - {@link angular.module.ng.$compileProvider.directive.input.url url}
+ * - {@link angular.module.ng.$compileProvider.directive.select select}
+ * - {@link angular.module.ng.$compileProvider.directive.textarea textarea}
+ *
+ */
var ngModelDirective = [function() {
return {
inject: {
@@ -942,6 +945,53 @@ var ngModelDirective = [function() {
}];
+/**
+ * @ngdoc directive
+ * @name angular.module.ng.$compileProvider.directive.ng:change
+ *
+ * @description
+ * Evaluate given expression when user changes the input.
+ * The expression is not evaluated when the value change is coming from the model.
+ *
+ * Note, this directive requires `ng:model` to be present.
+ *
+ * @element input
+ *
+ * @example
+ * <doc:example>
+ * <doc:source>
+ * <script>
+ * function Controller($scope) {
+ * $scope.counter = 0;
+ * $scope.change = function() {
+ * $scope.counter++;
+ * };
+ * }
+ * </script>
+ * <div ng:controller="Controller">
+ * <input type="checkbox" ng:model="confirmed" ng:change="change()" id="ng-change-example1" />
+ * <input type="checkbox" ng:model="confirmed" id="ng-change-example2" />
+ * <label for="ng-change-example2">Confirmed</label><br />
+ * debug = {{confirmed}}<br />
+ * counter = {{counter}}
+ * </div>
+ * </doc:source>
+ * <doc:scenario>
+ * it('should evaluate the expression if changing from view', function() {
+ * expect(binding('counter')).toEqual('0');
+ * element('#ng-change-example1').click();
+ * expect(binding('counter')).toEqual('1');
+ * expect(binding('confirmed')).toEqual('true');
+ * });
+ *
+ * it('should not evaluate the expression if changing from model', function() {
+ * element('#ng-change-example2').click();
+ * expect(binding('counter')).toEqual('0');
+ * expect(binding('confirmed')).toEqual('true');
+ * });
+ * </doc:scenario>
+ * </doc:example>
+ */
var ngChangeDirective = valueFn({
require: 'ngModel',
link: function(scope, element, attr, ctrl) {
@@ -952,6 +1002,38 @@ var ngChangeDirective = valueFn({
});
+/**
+ * @ngdoc directive
+ * @name angular.module.ng.$compileProvider.directive.ng:bind-immediate
+ *
+ * @element input
+ *
+ * @description
+ * By default, Angular udpates the model only on `blur` event - when the input looses focus.
+ * If you want to update after every key stroke, use `ng:bind-immediate`.
+ *
+ * @example
+ * <doc:example>
+ * <doc:source>
+ * First name: <input type="text" ng:model="firstName" /><br />
+ * Last name: <input type="text" ng:model="lastName" ng:bind-immediate /><br />
+ *
+ * First name ({{firstName}}) is only updated on `blur` event, but the last name ({{lastName}})
+ * is updated immediately, because of using `ng:bind-immediate`.
+ * </doc:source>
+ * <doc:scenario>
+ * it('should update first name on blur', function() {
+ * input('firstName').enter('santa', 'blur');
+ * expect(binding('firstName')).toEqual('santa');
+ * });
+ *
+ * it('should update last name immediately', function() {
+ * input('lastName').enter('santa', 'keydown');
+ * expect(binding('lastName')).toEqual('santa');
+ * });
+ * </doc:scenario>
+ * </doc:example>
+ */
var ngBindImmediateDirective = ['$browser', function($browser) {
return {
require: 'ngModel',
@@ -1005,3 +1087,83 @@ var requiredDirective = [function() {
}
};
}];
+
+
+/**
+ * @ngdoc directive
+ * @name angular.module.ng.$compileProvider.directive.ng:list
+ *
+ * @description
+ * Text input that converts between comma-seperated string into an array of strings.
+ *
+ * @param {string} ng:model Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the widgets is published.
+ * @param {string=} required Sets `REQUIRED` validation error key if the value is not entered.
+ * @param {string=} ng:pattern Sets `PATTERN` validation error key if the value does not match the
+ * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
+ * patterns defined as scope expressions.
+ * @param {string=} ng:change Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ *
+ * @element input
+ *
+ * @example
+ <doc:example>
+ <doc:source>
+ <script>
+ function Ctrl($scope) {
+ $scope.names = ['igor', 'misko', 'vojta'];
+ }
+ </script>
+ <form name="myForm" ng:controller="Ctrl">
+ List: <input type="list" name="input" ng:model="names" required>
+ <span class="error" ng:show="myForm.list.error.REQUIRED">
+ Required!</span>
+ <tt>names = {{names}}</tt><br/>
+ <tt>myForm.input.valid = {{myForm.input.valid}}</tt><br/>
+ <tt>myForm.input.error = {{myForm.input.error}}</tt><br/>
+ <tt>myForm.valid = {{myForm.valid}}</tt><br/>
+ <tt>myForm.error.REQUIRED = {{!!myForm.error.REQUIRED}}</tt><br/>
+ </form>
+ </doc:source>
+ <doc:scenario>
+ it('should initialize to model', function() {
+ expect(binding('names')).toEqual('["igor","misko","vojta"]');
+ expect(binding('myForm.input.valid')).toEqual('true');
+ });
+
+ it('should be invalid if empty', function() {
+ input('names').enter('');
+ expect(binding('names')).toEqual('');
+ expect(binding('myForm.input.valid')).toEqual('false');
+ });
+ </doc:scenario>
+ </doc:example>
+ */
+var ngListDirective = function() {
+ return {
+ require: 'ngModel',
+ link: function(scope, element, attr, ctrl) {
+ var parse = function(viewValue) {
+ var list = [];
+
+ if (viewValue) {
+ forEach(viewValue.split(/\s*,\s*/), function(value) {
+ if (value) list.push(value);
+ });
+ }
+
+ return list;
+ };
+
+ ctrl.parsers.push(parse);
+ ctrl.formatters.push(function(value) {
+ if (isArray(value) && !equals(parse(ctrl.viewValue), value)) {
+ return value.join(', ');
+ }
+
+ return undefined;
+ });
+ }
+ };
+};