diff options
Diffstat (limited to 'docs/content/cookbook/formadvanced.ngdoc')
| -rw-r--r-- | docs/content/cookbook/formadvanced.ngdoc | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/docs/content/cookbook/formadvanced.ngdoc b/docs/content/cookbook/formadvanced.ngdoc new file mode 100644 index 00000000..181dd5e9 --- /dev/null +++ b/docs/content/cookbook/formadvanced.ngdoc @@ -0,0 +1,105 @@ +@workInProgress +@ngdoc overview +@name Cookbook: Advanced Form +@description + +Here we extend the basic form example to include common features such as reverting, dirty state +detection, and preventing invalid form submission. + +<doc:example> + <doc:source> + <script> + UserForm.$inject = ['$invalidWidgets']; + function UserForm($invalidWidgets){ + this.$invalidWidgets = $invalidWidgets; + this.state = /^\w\w$/; + this.zip = /^\d\d\d\d\d$/; + this.master = { + name: 'John Smith', + address:{ + line1: '123 Main St.', + city:'Anytown', + state:'AA', + zip:'12345' + }, + contacts:[ + {type:'phone', value:'1(234) 555-1212'} + ] + }; + this.cancel(); + } + + UserForm.prototype = { + cancel: function(){ + this.form = angular.copy(this.master); + }, + + save: function(){ + this.master = this.form; + this.cancel(); + } + }; + </script> + <div ng:controller="UserForm"> + + <label>Name:</label><br/> + <input type="text" name="form.name" ng:required/> <br/><br/> + + <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>Phone:</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()" disabled="{{master.$equals(form)}}">Cancel</button> + <button ng:click="save()" disabled="{{$invalidWidgets.visible() || master.$equals(form)}}">Save</button> + + <hr/> + Debug View: + <pre>form={{form}} + master={{master}}</pre> + </div> + </doc:source> + <doc:scenario> + it('should enable save button', function(){ + expect(element(':button:contains(Save)').attr('disabled')).toBeTruthy(); + input('form.name').enter(''); + expect(element(':button:contains(Save)').attr('disabled')).toBeTruthy(); + input('form.name').enter('change'); + expect(element(':button:contains(Save)').attr('disabled')).toBeFalsy(); + element(':button:contains(Save)').click(); + expect(element(':button:contains(Save)').attr('disabled')).toBeTruthy(); + }); + it('should enable cancel button', function(){ + expect(element(':button:contains(Cancel)').attr('disabled')).toBeTruthy(); + input('form.name').enter('change'); + 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'); + }); + </doc:scenario> +</doc:example> + + +#Things to notice + +* Cancel & save buttons are only enabled if the form is dirty -- there is something to cancel or + save. +* Save button is only enabled if there are no validation errors on the form. +* Cancel reverts the form changes back to original state. +* Save updates the internal model of the form. +* Debug view shows the two models. One presented to the user form and the other being the pristine + copy master. |
