mirror of
https://github.com/zhigang1992/angular.js.git
synced 2026-04-27 19:13:55 +08:00
feat(forms): new and improved forms
This commit is contained in:
@@ -9,9 +9,7 @@ detection, and preventing invalid form submission.
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
<script>
|
||||
UserForm.$inject = ['$invalidWidgets'];
|
||||
function UserForm($invalidWidgets){
|
||||
this.$invalidWidgets = $invalidWidgets;
|
||||
function UserForm(){
|
||||
this.state = /^\w\w$/;
|
||||
this.zip = /^\d\d\d\d\d$/;
|
||||
this.master = {
|
||||
@@ -42,31 +40,34 @@ detection, and preventing invalid form submission.
|
||||
</script>
|
||||
<div ng:controller="UserForm">
|
||||
|
||||
<label>Name:</label><br/>
|
||||
<input type="text" name="form.name" ng:required/> <br/><br/>
|
||||
<form name="myForm">
|
||||
|
||||
<label>Address:</label><br/>
|
||||
<input type="text" name="form.address.line1" size="33" ng:required/> <br/>
|
||||
<input type="text" name="form.address.city" size="12" ng:required/>,
|
||||
<input type="text" name="form.address.state" size="2" ng:required ng:validate="regexp:state"/>
|
||||
<input type="text" name="form.address.zip" size="5" ng:required
|
||||
ng:validate="regexp:zip"/><br/><br/>
|
||||
<label>Name:</label><br/>
|
||||
<input type="text" ng:model="form.name" required/> <br/><br/>
|
||||
|
||||
<label>Contacts:</label>
|
||||
[ <a href="" ng:click="form.contacts.$add()">add</a> ]
|
||||
<div ng:repeat="contact in form.contacts">
|
||||
<select name="contact.type">
|
||||
<option>email</option>
|
||||
<option>phone</option>
|
||||
<option>pager</option>
|
||||
<option>IM</option>
|
||||
</select>
|
||||
<input type="text" name="contact.value" ng:required/>
|
||||
[ <a href="" ng:click="form.contacts.$remove(contact)">X</a> ]
|
||||
</div>
|
||||
<button ng:click="cancel()" ng:disabled="{{master.$equals(form)}}">Cancel</button>
|
||||
<button ng:click="save()" ng:disabled="{{$invalidWidgets.visible() ||
|
||||
master.$equals(form)}}">Save</button>
|
||||
<label>Address:</label> <br/>
|
||||
<input type="text" ng:model="form.address.line1" size="33" required/> <br/>
|
||||
<input type="text" ng:model="form.address.city" size="12" required/>,
|
||||
<input type="text" ng:model="form.address.state" size="2"
|
||||
ng:pattern="state" required/>
|
||||
<input type="text" ng:model="form.address.zip" size="5"
|
||||
ng:pattern="zip" required/><br/><br/>
|
||||
|
||||
<label>Contacts:</label>
|
||||
[ <a href="" ng:click="form.contacts.$add()">add</a> ]
|
||||
<div ng:repeat="contact in form.contacts">
|
||||
<select ng:model="contact.type">
|
||||
<option>email</option>
|
||||
<option>phone</option>
|
||||
<option>pager</option>
|
||||
<option>IM</option>
|
||||
</select>
|
||||
<input type="text" ng:model="contact.value" required/>
|
||||
[ <a href="" ng:click="form.contacts.$remove(contact)">X</a> ]
|
||||
</div>
|
||||
<button ng:click="cancel()" ng:disabled="{{master.$equals(form)}}">Cancel</button>
|
||||
<button ng:click="save()" ng:disabled="{{myForm.$invalid || master.$equals(form)}}">Save</button>
|
||||
</form>
|
||||
|
||||
<hr/>
|
||||
Debug View:
|
||||
@@ -90,7 +91,7 @@ master.$equals(form)}}">Save</button>
|
||||
expect(element(':button:contains(Cancel)').attr('disabled')).toBeFalsy();
|
||||
element(':button:contains(Cancel)').click();
|
||||
expect(element(':button:contains(Cancel)').attr('disabled')).toBeTruthy();
|
||||
expect(element(':input[name="form.name"]').val()).toEqual('John Smith');
|
||||
expect(element(':input[ng\\:model="form.name"]').val()).toEqual('John Smith');
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
|
||||
@@ -15,6 +15,7 @@ to retrieve Buzz activity and comments.
|
||||
<script>
|
||||
BuzzController.$inject = ['$resource'];
|
||||
function BuzzController($resource) {
|
||||
this.userId = 'googlebuzz';
|
||||
this.Activity = $resource(
|
||||
'https://www.googleapis.com/buzz/v1/activities/:userId/:visibility/:activityId/:comments',
|
||||
{alt: 'json', callback: 'JSON_CALLBACK'},
|
||||
@@ -32,7 +33,7 @@ to retrieve Buzz activity and comments.
|
||||
};
|
||||
</script>
|
||||
<div ng:controller="BuzzController">
|
||||
<input name="userId" value="googlebuzz"/>
|
||||
<input ng:model="userId"/>
|
||||
<button ng:click="fetch()">fetch</button>
|
||||
<hr/>
|
||||
<div class="buzz" ng:repeat="item in activities.data.items">
|
||||
|
||||
@@ -24,25 +24,26 @@ allow a user to enter data.
|
||||
<div ng:controller="FormController" class="example">
|
||||
|
||||
<label>Name:</label><br/>
|
||||
<input type="text" name="user.name" ng:required/> <br/><br/>
|
||||
<input type="text" ng:model="user.name" required/> <br/><br/>
|
||||
|
||||
<label>Address:</label><br/>
|
||||
<input type="text" name="user.address.line1" size="33" ng:required/> <br/>
|
||||
<input type="text" name="user.address.city" size="12" ng:required/>,
|
||||
<input type="text" name="user.address.state" size="2" ng:required ng:validate="regexp:state"/>
|
||||
<input type="text" name="user.address.zip" size="5" ng:required
|
||||
ng:validate="regexp:zip"/><br/><br/>
|
||||
<input type="text" ng:model="user.address.line1" size="33" required> <br/>
|
||||
<input type="text" ng:model="user.address.city" size="12" required>,
|
||||
<input type="text" ng:model="user.address.state" size="2"
|
||||
ng:pattern="state" required>
|
||||
<input type="text" ng:model="user.address.zip" size="5"
|
||||
ng:pattern="zip" required><br/><br/>
|
||||
|
||||
<label>Phone:</label>
|
||||
[ <a href="" ng:click="user.contacts.$add()">add</a> ]
|
||||
<div ng:repeat="contact in user.contacts">
|
||||
<select name="contact.type">
|
||||
<select ng:model="contact.type">
|
||||
<option>email</option>
|
||||
<option>phone</option>
|
||||
<option>pager</option>
|
||||
<option>IM</option>
|
||||
</select>
|
||||
<input type="text" name="contact.value" ng:required/>
|
||||
<input type="text" ng:model="contact.value" required/>
|
||||
[ <a href="" ng:click="user.contacts.$remove(contact)">X</a> ]
|
||||
</div>
|
||||
<hr/>
|
||||
@@ -68,19 +69,21 @@ ng:validate="regexp:zip"/><br/><br/>
|
||||
});
|
||||
|
||||
it('should validate zip', function(){
|
||||
expect(using('.example').element(':input[name="user.address.zip"]').prop('className'))
|
||||
.not().toMatch(/ng-validation-error/);
|
||||
expect(using('.example').
|
||||
element(':input[ng\\:model="user.address.zip"]').
|
||||
prop('className')).not().toMatch(/ng-invalid/);
|
||||
using('.example').input('user.address.zip').enter('abc');
|
||||
expect(using('.example').element(':input[name="user.address.zip"]').prop('className'))
|
||||
.toMatch(/ng-validation-error/);
|
||||
expect(using('.example').
|
||||
element(':input[ng\\:model="user.address.zip"]').
|
||||
prop('className')).toMatch(/ng-invalid/);
|
||||
});
|
||||
|
||||
it('should validate state', function(){
|
||||
expect(using('.example').element(':input[name="user.address.state"]').prop('className'))
|
||||
.not().toMatch(/ng-validation-error/);
|
||||
expect(using('.example').element(':input[ng\\:model="user.address.state"]').prop('className'))
|
||||
.not().toMatch(/ng-invalid/);
|
||||
using('.example').input('user.address.state').enter('XXX');
|
||||
expect(using('.example').element(':input[name="user.address.state"]').prop('className'))
|
||||
.toMatch(/ng-validation-error/);
|
||||
expect(using('.example').element(':input[ng\\:model="user.address.state"]').prop('className'))
|
||||
.toMatch(/ng-invalid/);
|
||||
});
|
||||
</doc:scenario>
|
||||
</doc:example>
|
||||
@@ -94,7 +97,7 @@ available in
|
||||
* For debugging purposes we have included a debug view of the model to better understand what
|
||||
is going on.
|
||||
* The {@link api/angular.widget.HTML input widgets} simply refer to the model and are auto bound.
|
||||
* The inputs {@link api/angular.validator validate}. (Try leaving them blank or entering non digits
|
||||
* The inputs {@link guide/dev_guide.forms validate}. (Try leaving them blank or entering non digits
|
||||
in the zip field)
|
||||
* In your application you can simply read from or write to the model and the form will be updated.
|
||||
* By clicking the 'add' link you are adding new items into the `user.contacts` array which are then
|
||||
|
||||
@@ -5,9 +5,16 @@
|
||||
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
Your name: <input type="text" name="name" value="World"/>
|
||||
<hr/>
|
||||
Hello {{name}}!
|
||||
<script>
|
||||
function HelloCntl(){
|
||||
this.name = 'World';
|
||||
}
|
||||
</script>
|
||||
<div ng:controller="HelloCntl">
|
||||
Your name: <input type="text" ng:model="name" value="World"/>
|
||||
<hr/>
|
||||
Hello {{name}}!
|
||||
</div>
|
||||
</doc:source>
|
||||
<doc:scenario>
|
||||
it('should change the binding when user enters text', function(){
|
||||
|
||||
Reference in New Issue
Block a user