aboutsummaryrefslogtreecommitdiffstats
path: root/docs/content/cookbook/advancedform.ngdoc
diff options
context:
space:
mode:
Diffstat (limited to 'docs/content/cookbook/advancedform.ngdoc')
-rw-r--r--docs/content/cookbook/advancedform.ngdoc123
1 files changed, 123 insertions, 0 deletions
diff --git a/docs/content/cookbook/advancedform.ngdoc b/docs/content/cookbook/advancedform.ngdoc
new file mode 100644
index 00000000..e14be8b4
--- /dev/null
+++ b/docs/content/cookbook/advancedform.ngdoc
@@ -0,0 +1,123 @@
+@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.
+
+
+
+
+