mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-03-16 23:30:23 +00:00
Added documentation for validators.
BACKWARD INCOMPATIBLE: removed ssn validators, since it is unlikely that most people will need it and if they do, they can added it thorough RegExp
This commit is contained in:
parent
5be325a0c1
commit
91b6c5f7ff
7 changed files with 350 additions and 42 deletions
|
|
@ -9,6 +9,11 @@
|
|||
<input type="text" ng:validate="{{shortName}}{{#paramRest}}{{^default}}:{{name}}{{/default}}{{#default}}<i>[:{{name}}]</i>{{/default}}{{/paramRest}}"/>
|
||||
</tt>
|
||||
|
||||
<h3>In JavaScript</h3>
|
||||
<tt ng:non-bindable>
|
||||
angular.validator.{{shortName}}({{paramFirst.name}}{{#paramRest}}{{^default}}, {{name}}{{/default}}{{#default}}<i>[, {{name}}]</i>{{/default}}{{/paramRest}} );
|
||||
</tt>
|
||||
|
||||
<h3>Parameters</h3>
|
||||
<ul>
|
||||
{{#param}}
|
||||
|
|
|
|||
|
|
@ -343,7 +343,7 @@ snippet</p></textarea>
|
|||
});
|
||||
|
||||
it('should update', function(){
|
||||
textarea('snippet').enter('new <b>text</b>');
|
||||
input('snippet').enter('new <b>text</b>');
|
||||
expect(using('#html-filter').binding('snippet | html')).toBe('new <b>text</b>');
|
||||
expect(using('#escaped-html').binding('snippet')).toBe("new <b>text</b>");
|
||||
expect(using('#html-unsafe-filter').binding("snippet | html:'unsafe'")).toBe('new <b>text</b>');
|
||||
|
|
@ -415,7 +415,7 @@ and one more: ftp://127.0.0.1/.</textarea>
|
|||
});
|
||||
|
||||
it('should update', function(){
|
||||
textarea('snippet').enter('new http://link.');
|
||||
input('snippet').enter('new http://link.');
|
||||
expect(using('#linky-filter').binding('snippet | linky')).
|
||||
toBe('new <a href="http://link">http://link</a>.');
|
||||
expect(using('#escaped-html').binding('snippet')).toBe('new http://link.');
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ angular.scenario.dsl('input', function() {
|
|||
|
||||
chain.enter = function(value) {
|
||||
return this.addFutureAction("input '" + this.name + "' enter '" + value + "'", function($window, $document, done) {
|
||||
var input = $document.elements('input[name="$1"]', this.name);
|
||||
var input = $document.elements(':input[name="$1"]', this.name);
|
||||
input.val(value);
|
||||
input.trigger('change');
|
||||
done();
|
||||
|
|
@ -200,7 +200,7 @@ angular.scenario.dsl('input', function() {
|
|||
|
||||
chain.check = function() {
|
||||
return this.addFutureAction("checkbox '" + this.name + "' toggle", function($window, $document, done) {
|
||||
var input = $document.elements('input:checkbox[name="$1"]', this.name);
|
||||
var input = $document.elements(':checkbox[name="$1"]', this.name);
|
||||
input.trigger('click');
|
||||
done();
|
||||
});
|
||||
|
|
@ -209,7 +209,7 @@ angular.scenario.dsl('input', function() {
|
|||
chain.select = function(value) {
|
||||
return this.addFutureAction("radio button '" + this.name + "' toggle '" + value + "'", function($window, $document, done) {
|
||||
var input = $document.
|
||||
elements('input:radio[name$="@$1"][value="$2"]', this.name, value);
|
||||
elements(':radio[name$="@$1"][value="$2"]', this.name, value);
|
||||
input.trigger('click');
|
||||
done();
|
||||
});
|
||||
|
|
@ -222,29 +222,6 @@ angular.scenario.dsl('input', function() {
|
|||
});
|
||||
|
||||
|
||||
/**
|
||||
* Usage:
|
||||
* textarea(name).enter(value) enters value in the text area with specified name
|
||||
*/
|
||||
angular.scenario.dsl('textarea', function() {
|
||||
var chain = {};
|
||||
|
||||
chain.enter = function(value) {
|
||||
return this.addFutureAction("textarea '" + this.name + "' enter '" + value + "'", function($window, $document, done) {
|
||||
var textarea = $document.elements('textarea[name="$1"]', this.name);
|
||||
textarea.val(value);
|
||||
textarea.trigger('change');
|
||||
done();
|
||||
});
|
||||
};
|
||||
|
||||
return function(name) {
|
||||
this.name = name;
|
||||
return chain;
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Usage:
|
||||
* repeater('#products table', 'Product List').count() number of rows
|
||||
|
|
|
|||
|
|
@ -1,6 +1,31 @@
|
|||
extend(angularValidator, {
|
||||
'noop': function() { return _null; },
|
||||
|
||||
/**
|
||||
* @ngdoc validator
|
||||
* @name angular.validator.regexp
|
||||
* @description
|
||||
* Use regexp validator to restrict the input to any Regular Expression.
|
||||
*
|
||||
* @param {string} value value to validate
|
||||
* @param {regexp} expression regular expression.
|
||||
* @css ng-validation-error
|
||||
*
|
||||
* @example
|
||||
* Enter valid SSN:
|
||||
* <input name="ssn" value="123-45-6789" ng:validate="regexp:/^\d\d\d-\d\d-\d\d\d\d$/" >
|
||||
*
|
||||
* @scenario
|
||||
* it('should invalidate non ssn', function(){
|
||||
* var textBox = element('.example :input');
|
||||
* expect(textBox.attr('className')).not().toMatch(/ng-validation-error/);
|
||||
* expect(textBox.val()).toEqual('123-45-6789');
|
||||
*
|
||||
* input('ssn').enter('123-45-67890');
|
||||
* expect(textBox.attr('className')).toMatch(/ng-validation-error/);
|
||||
* });
|
||||
*
|
||||
*/
|
||||
'regexp': function(value, regexp, msg) {
|
||||
if (!value.match(regexp)) {
|
||||
return msg ||
|
||||
|
|
@ -10,6 +35,43 @@ extend(angularValidator, {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc validator
|
||||
* @name angular.validator.number
|
||||
* @description
|
||||
* Use number validator to restrict the input to numbers with an
|
||||
* optional range. (See integer for whole numbers validator).
|
||||
*
|
||||
* @param {string} value value to validate
|
||||
* @param {int=} [min=MIN_INT] minimum value.
|
||||
* @param {int=} [max=MAX_INT] maximum value.
|
||||
* @css ng-validation-error
|
||||
*
|
||||
* @example
|
||||
* Enter number: <input name="n1" ng:validate="number" > <br>
|
||||
* Enter number greater than 10: <input name="n2" ng:validate="number:10" > <br>
|
||||
* Enter number between 100 and 200: <input name="n3" ng:validate="number:100:200" > <br>
|
||||
*
|
||||
* @scenario
|
||||
* it('should invalidate number', function(){
|
||||
* var n1 = element('.example :input[name=n1]');
|
||||
* expect(n1.attr('className')).not().toMatch(/ng-validation-error/);
|
||||
* input('n1').enter('1.x');
|
||||
* expect(n1.attr('className')).toMatch(/ng-validation-error/);
|
||||
*
|
||||
* var n2 = element('.example :input[name=n2]');
|
||||
* expect(n2.attr('className')).not().toMatch(/ng-validation-error/);
|
||||
* input('n2').enter('9');
|
||||
* expect(n2.attr('className')).toMatch(/ng-validation-error/);
|
||||
*
|
||||
* var n3 = element('.example :input[name=n3]');
|
||||
* expect(n3.attr('className')).not().toMatch(/ng-validation-error/);
|
||||
* input('n3').enter('201');
|
||||
* expect(n3.attr('className')).toMatch(/ng-validation-error/);
|
||||
*
|
||||
* });
|
||||
*
|
||||
*/
|
||||
'number': function(value, min, max) {
|
||||
var num = 1 * value;
|
||||
if (num == value) {
|
||||
|
|
@ -25,6 +87,42 @@ extend(angularValidator, {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc validator
|
||||
* @name angular.validator.integer
|
||||
* @description
|
||||
* Use number validator to restrict the input to integers with an
|
||||
* optional range. (See integer for whole numbers validator).
|
||||
*
|
||||
* @param {string} value value to validate
|
||||
* @param {int=} [min=MIN_INT] minimum value.
|
||||
* @param {int=} [max=MAX_INT] maximum value.
|
||||
* @css ng-validation-error
|
||||
*
|
||||
* @example
|
||||
* Enter integer: <input name="n1" ng:validate="integer" > <br>
|
||||
* Enter integer equal or greater than 10: <input name="n2" ng:validate="integer:10" > <br>
|
||||
* Enter integer between 100 and 200 (inclusive): <input name="n3" ng:validate="integer:100:200" > <br>
|
||||
*
|
||||
* @scenario
|
||||
* it('should invalidate integer', function(){
|
||||
* var n1 = element('.example :input[name=n1]');
|
||||
* expect(n1.attr('className')).not().toMatch(/ng-validation-error/);
|
||||
* input('n1').enter('1.1');
|
||||
* expect(n1.attr('className')).toMatch(/ng-validation-error/);
|
||||
*
|
||||
* var n2 = element('.example :input[name=n2]');
|
||||
* expect(n2.attr('className')).not().toMatch(/ng-validation-error/);
|
||||
* input('n2').enter('10.1');
|
||||
* expect(n2.attr('className')).toMatch(/ng-validation-error/);
|
||||
*
|
||||
* var n3 = element('.example :input[name=n3]');
|
||||
* expect(n3.attr('className')).not().toMatch(/ng-validation-error/);
|
||||
* input('n3').enter('100.1');
|
||||
* expect(n3.attr('className')).toMatch(/ng-validation-error/);
|
||||
*
|
||||
* });
|
||||
*/
|
||||
'integer': function(value, min, max) {
|
||||
var numberError = angularValidator['number'](value, min, max);
|
||||
if (numberError) return numberError;
|
||||
|
|
@ -34,6 +132,29 @@ extend(angularValidator, {
|
|||
return _null;
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc validator
|
||||
* @name angular.validator.date
|
||||
* @description
|
||||
* Use date validator to restrict the user input to a valid date
|
||||
* in format in format MM/DD/YYYY.
|
||||
*
|
||||
* @param {string} value value to validate
|
||||
* @css ng-validation-error
|
||||
*
|
||||
* @example
|
||||
* Enter valid date:
|
||||
* <input name="text" value="1/1/2009" ng:validate="date" >
|
||||
*
|
||||
* @scenario
|
||||
* it('should invalidate date', function(){
|
||||
* var n1 = element('.example :input');
|
||||
* expect(n1.attr('className')).not().toMatch(/ng-validation-error/);
|
||||
* input('text').enter('123/123/123');
|
||||
* expect(n1.attr('className')).toMatch(/ng-validation-error/);
|
||||
* });
|
||||
*
|
||||
*/
|
||||
'date': function(value) {
|
||||
var fields = /^(\d\d?)\/(\d\d?)\/(\d\d\d\d)$/.exec(value);
|
||||
var date = fields ? new Date(fields[3], fields[1]-1, fields[2]) : 0;
|
||||
|
|
@ -44,13 +165,28 @@ extend(angularValidator, {
|
|||
_null : "Value is not a date. (Expecting format: 12/31/2009).";
|
||||
},
|
||||
|
||||
'ssn': function(value) {
|
||||
if (value.match(/^\d\d\d-\d\d-\d\d\d\d$/)) {
|
||||
return _null;
|
||||
}
|
||||
return "SSN needs to be in 999-99-9999 format.";
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc validator
|
||||
* @name angular.validator.email
|
||||
* @description
|
||||
* Use email validator if you wist to restrict the user input to a valid email.
|
||||
*
|
||||
* @param {string} value value to validate
|
||||
* @css ng-validation-error
|
||||
*
|
||||
* @example
|
||||
* Enter valid email:
|
||||
* <input name="text" ng:validate="email" value="me@example.com">
|
||||
*
|
||||
* @scenario
|
||||
* it('should invalidate email', function(){
|
||||
* var n1 = element('.example :input');
|
||||
* expect(n1.attr('className')).not().toMatch(/ng-validation-error/);
|
||||
* input('text').enter('a@b.c');
|
||||
* expect(n1.attr('className')).toMatch(/ng-validation-error/);
|
||||
* });
|
||||
*
|
||||
*/
|
||||
'email': function(value) {
|
||||
if (value.match(/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$/)) {
|
||||
return _null;
|
||||
|
|
@ -58,6 +194,28 @@ extend(angularValidator, {
|
|||
return "Email needs to be in username@host.com format.";
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc validator
|
||||
* @name angular.validator.phone
|
||||
* @description
|
||||
* Use phone validator to restrict the input phone numbers.
|
||||
*
|
||||
* @param {string} value value to validate
|
||||
* @css ng-validation-error
|
||||
*
|
||||
* @example
|
||||
* Enter valid phone number:
|
||||
* <input name="text" value="1(234)567-8901" ng:validate="phone" >
|
||||
*
|
||||
* @scenario
|
||||
* it('should invalidate phone', function(){
|
||||
* var n1 = element('.example :input');
|
||||
* expect(n1.attr('className')).not().toMatch(/ng-validation-error/);
|
||||
* input('text').enter('+12345678');
|
||||
* expect(n1.attr('className')).toMatch(/ng-validation-error/);
|
||||
* });
|
||||
*
|
||||
*/
|
||||
'phone': function(value) {
|
||||
if (value.match(/^1\(\d\d\d\)\d\d\d-\d\d\d\d$/)) {
|
||||
return _null;
|
||||
|
|
@ -68,6 +226,28 @@ extend(angularValidator, {
|
|||
return "Phone number needs to be in 1(987)654-3210 format in North America or +999 (123) 45678 906 internationaly.";
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc validator
|
||||
* @name angular.validator.url
|
||||
* @description
|
||||
* Use phone validator to restrict the input URLs.
|
||||
*
|
||||
* @param {string} value value to validate
|
||||
* @css ng-validation-error
|
||||
*
|
||||
* @example
|
||||
* Enter valid phone number:
|
||||
* <input name="text" value="http://example.com/abc.html" size="40" ng:validate="url" >
|
||||
*
|
||||
* @scenario
|
||||
* it('should invalidate url', function(){
|
||||
* var n1 = element('.example :input');
|
||||
* expect(n1.attr('className')).not().toMatch(/ng-validation-error/);
|
||||
* input('text').enter('abc://server/path');
|
||||
* expect(n1.attr('className')).toMatch(/ng-validation-error/);
|
||||
* });
|
||||
*
|
||||
*/
|
||||
'url': function(value) {
|
||||
if (value.match(/^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/)) {
|
||||
return _null;
|
||||
|
|
@ -75,6 +255,29 @@ extend(angularValidator, {
|
|||
return "URL needs to be in http://server[:port]/path format.";
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc validator
|
||||
* @name angular.validator.json
|
||||
* @description
|
||||
* Use json validator if you wish to restrict the user input to a valid JSON.
|
||||
*
|
||||
* @param {string} value value to validate
|
||||
* @css ng-validation-error
|
||||
*
|
||||
* @example
|
||||
* <textarea name="json" cols="60" rows="5" ng:validate="json">
|
||||
* {name:'abc'}
|
||||
* </textarea>
|
||||
*
|
||||
* @scenario
|
||||
* it('should invalidate json', function(){
|
||||
* var n1 = element('.example :input');
|
||||
* expect(n1.attr('className')).not().toMatch(/ng-validation-error/);
|
||||
* input('json').enter('{name}');
|
||||
* expect(n1.attr('className')).toMatch(/ng-validation-error/);
|
||||
* });
|
||||
*
|
||||
*/
|
||||
'json': function(value) {
|
||||
try {
|
||||
fromJson(value);
|
||||
|
|
|
|||
129
src/widgets.js
129
src/widgets.js
|
|
@ -1,5 +1,134 @@
|
|||
/**
|
||||
* @ngdoc widget
|
||||
* @name angular.widget.HTML
|
||||
*
|
||||
* @description
|
||||
* The most common widgets you will use will be in the from of the
|
||||
* standard HTML set. These widgets are bound using the name attribute
|
||||
* to an expression. In addition they can have `ng:validate`, `ng:required`,
|
||||
* `ng:format`, `ng:change` attribute to further control their behavior.
|
||||
*
|
||||
* @usageContent
|
||||
* see example below for usage
|
||||
*
|
||||
* <input type="text|checkbox|..." ... />
|
||||
* <textarea ... />
|
||||
* <select ...>
|
||||
* <option>...</option>
|
||||
* </select>
|
||||
*
|
||||
* @example
|
||||
<table style="font-size:.9em;">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Format</th>
|
||||
<th>HTML</th>
|
||||
<th>UI</th>
|
||||
<th ng:non-bindable>{{input#}}</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>text</th>
|
||||
<td>String</td>
|
||||
<td><tt><input type="text" name="input1"></tt></td>
|
||||
<td><input type="text" name="input1" size="4"></td>
|
||||
<td><tt>{{input1|json}}</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>textarea</th>
|
||||
<td>String</td>
|
||||
<td><tt><textarea name="input2"></textarea></tt></td>
|
||||
<td><textarea name="input2" cols='6'></textarea></td>
|
||||
<td><tt>{{input2|json}}</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>radio</th>
|
||||
<td>String</td>
|
||||
<td><tt>
|
||||
<input type="radio" name="input3" value="A"><br>
|
||||
<input type="radio" name="input3" value="B">
|
||||
</tt></td>
|
||||
<td>
|
||||
<input type="radio" name="input3" value="A">
|
||||
<input type="radio" name="input3" value="B">
|
||||
</td>
|
||||
<td><tt>{{input3|json}}</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>checkbox</th>
|
||||
<td>Boolean</td>
|
||||
<td><tt><input type="checkbox" name="input4" value="checked"></tt></td>
|
||||
<td><input type="checkbox" name="input4" value="checked"></td>
|
||||
<td><tt>{{input4|json}}</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>pulldown</th>
|
||||
<td>String</td>
|
||||
<td><tt>
|
||||
<select name="input5"><br>
|
||||
<option value="c">C</option><br>
|
||||
<option value="d">D</option><br>
|
||||
</select><br>
|
||||
</tt></td>
|
||||
<td>
|
||||
<select name="input5">
|
||||
<option value="c">C</option>
|
||||
<option value="d">D</option>
|
||||
</select>
|
||||
</td>
|
||||
<td><tt>{{input5|json}}</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>multiselect</th>
|
||||
<td>Array</td>
|
||||
<td><tt>
|
||||
<select name="input6" multiple size="4"><br>
|
||||
<option value="e">E</option><br>
|
||||
<option value="f">F</option><br>
|
||||
</select><br>
|
||||
</tt></td>
|
||||
<td>
|
||||
<select name="input6" multiple size="4">
|
||||
<option value="e">E</option>
|
||||
<option value="f">F</option>
|
||||
</select>
|
||||
</td>
|
||||
<td><tt>{{input6|json}}</tt></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
* @scenario
|
||||
* it('should exercise text', function(){
|
||||
* input('input1').enter('Carlos');
|
||||
* expect(binding('input1')).toEqual('"Carlos"');
|
||||
* });
|
||||
* it('should exercise textarea', function(){
|
||||
* input('input2').enter('Carlos');
|
||||
* expect(binding('input2')).toEqual('"Carlos"');
|
||||
* });
|
||||
* it('should exercise radio', function(){
|
||||
* expect(binding('input3')).toEqual('null');
|
||||
* input('input3').select('A');
|
||||
* expect(binding('input3')).toEqual('"A"');
|
||||
* input('input3').select('B');
|
||||
* expect(binding('input3')).toEqual('"B"');
|
||||
* });
|
||||
* it('should exercise checkbox', function(){
|
||||
* expect(binding('input4')).toEqual('false');
|
||||
* input('input4').check();
|
||||
* expect(binding('input4')).toEqual('true');
|
||||
* });
|
||||
* it('should exercise pulldown', function(){
|
||||
* expect(binding('input5')).toEqual('"c"');
|
||||
* select('input5').option('d');
|
||||
* expect(binding('input5')).toEqual('"d"');
|
||||
* });
|
||||
* it('should exercise multiselect', function(){
|
||||
* expect(binding('input6')).toEqual('[]');
|
||||
* select('input6').options('e');
|
||||
* expect(binding('input6')).toEqual('["e"]');
|
||||
* select('input6').options('e', 'f');
|
||||
* expect(binding('input6')).toEqual('["e","f"]');
|
||||
* });
|
||||
*/
|
||||
|
||||
function modelAccessor(scope, element) {
|
||||
|
|
|
|||
|
|
@ -69,12 +69,6 @@ ValidatorTest.prototype.testPhone = function() {
|
|||
assertEquals(null, angular.validator.phone("+421 0905 933 297"));
|
||||
};
|
||||
|
||||
ValidatorTest.prototype.testSSN = function() {
|
||||
var error = "SSN needs to be in 999-99-9999 format.";
|
||||
assertEquals(angular.validator.ssn("ab"), error);
|
||||
assertEquals(angular.validator.ssn("123-45-6789"), null);
|
||||
};
|
||||
|
||||
ValidatorTest.prototype.testURL = function() {
|
||||
var error = "URL needs to be in http://server[:port]/path format.";
|
||||
assertEquals(angular.validator.url("ab"), error);
|
||||
|
|
|
|||
|
|
@ -509,7 +509,7 @@ describe("angular.scenario.dsl", function() {
|
|||
|
||||
it('should change value in textarea', function() {
|
||||
doc.append('<textarea name="test.textarea">something</textarea>');
|
||||
var chain = $root.dsl.textarea('test.textarea');
|
||||
var chain = $root.dsl.input('test.textarea');
|
||||
chain.enter('foo');
|
||||
expect(_jQuery('textarea[name="test.textarea"]').val()).toEqual('foo');
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue