Skip to content

Commit ef23fe6

Browse files
committed
docs(forms): Document the rest of the forms module.
Closes angular#4437
1 parent 993b3d6 commit ef23fe6

12 files changed

Lines changed: 198 additions & 73 deletions

modules/angular2/src/core/forms/directives/abstract_control_directive.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@ import {AbstractControl} from '../model';
22
import {isPresent} from 'angular2/src/core/facade/lang';
33
import {unimplemented} from 'angular2/src/core/facade/exceptions';
44

5+
/**
6+
* Base class for control directives.
7+
*
8+
* Only used internally in the forms module.
9+
*/
510
export abstract class AbstractControlDirective {
611
get control(): AbstractControl { return unimplemented(); }
712

modules/angular2/src/core/forms/directives/checkbox_value_accessor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const CHECKBOX_VALUE_ACCESSOR = CONST_EXPR(new Provider(
1515
*
1616
* ### Example
1717
* ```
18-
* <input type="checkbox" [ng-control]="rememberLogin">
18+
* <input type="checkbox" ng-control="rememberLogin">
1919
* ```
2020
*/
2121
@Directive({

modules/angular2/src/core/forms/directives/control_container.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,20 @@ import {Form} from './form_interface';
22
import {AbstractControlDirective} from './abstract_control_directive';
33

44
/**
5-
* A directive that contains multiple {@link NgControl}.
5+
* A directive that contains multiple {@link NgControl}s.
66
*
77
* Only used by the forms module.
88
*/
99
export class ControlContainer extends AbstractControlDirective {
1010
name: string;
11+
12+
/**
13+
* Get the form to which this container belongs.
14+
*/
1115
get formDirective(): Form { return null; }
16+
17+
/**
18+
* Get the path to this container.
19+
*/
1220
get path(): string[] { return null; }
1321
}

modules/angular2/src/core/forms/directives/control_value_accessor.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,25 @@ import {OpaqueToken} from 'angular2/src/core/di';
44
/**
55
* A bridge between a control and a native element.
66
*
7+
* A `ControlValueAccessor` abstracts the operations of writing a new value to a
8+
* DOM element representing an input control.
9+
*
710
* Please see {@link DefaultValueAccessor} for more information.
811
*/
912
export interface ControlValueAccessor {
13+
/**
14+
* Write a new value to the element.
15+
*/
1016
writeValue(obj: any): void;
17+
18+
/**
19+
* Set the function to be called when the control receives a change event.
20+
*/
1121
registerOnChange(fn: any): void;
22+
23+
/**
24+
* Set the function to be called when the control receives a touch event.
25+
*/
1226
registerOnTouched(fn: any): void;
1327
}
1428

modules/angular2/src/core/forms/directives/default_value_accessor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const DEFAULT_VALUE_ACCESSOR = CONST_EXPR(new Provider(
1515
*
1616
* ### Example
1717
* ```
18-
* <input type="text" [(ng-model)]="searchQuery">
18+
* <input type="text" ng-control="searchQuery">
1919
* ```
2020
*/
2121
@Directive({

modules/angular2/src/core/forms/directives/form_interface.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,38 @@ import {Control, ControlGroup} from '../model';
88
* Only used by the forms module.
99
*/
1010
export interface Form {
11+
/**
12+
* Add a control to this form.
13+
*/
1114
addControl(dir: NgControl): void;
15+
16+
/**
17+
* Remove a control from this form.
18+
*/
1219
removeControl(dir: NgControl): void;
20+
21+
/**
22+
* Look up the {@link Control} associated with a particular {@link NgControl}.
23+
*/
1324
getControl(dir: NgControl): Control;
25+
26+
/**
27+
* Add a group of controls to this form.
28+
*/
1429
addControlGroup(dir: NgControlGroup): void;
30+
31+
/**
32+
* Remove a group of controls from this form.
33+
*/
1534
removeControlGroup(dir: NgControlGroup): void;
35+
36+
/**
37+
* Look up the {@link ControlGroup} associated with a particular {@link NgControlGroup}.
38+
*/
1639
getControlGroup(dir: NgControlGroup): ControlGroup;
40+
41+
/**
42+
* Update the model for a particular control with a new value.
43+
*/
1744
updateModel(dir: NgControl, value: any): void;
1845
}

modules/angular2/src/core/forms/directives/ng_control.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,9 @@ import {unimplemented} from 'angular2/src/core/facade/exceptions';
55
/**
66
* A base class that all control directive extend.
77
* It binds a {@link Control} object to a DOM element.
8+
*
9+
* Used internally by Angular forms.
810
*/
9-
// Cannot currently be abstract because it would contain
10-
// an abstract method in the public API, and we cannot reflect
11-
// on that in Dart due to https://github.com/dart-lang/sdk/issues/18721
12-
// Also we don't have abstract setters, see https://github.com/Microsoft/TypeScript/issues/4669
1311
export abstract class NgControl extends AbstractControlDirective {
1412
name: string = null;
1513
valueAccessor: ControlValueAccessor = null;

modules/angular2/src/core/forms/directives/ng_control_group.ts

Lines changed: 49 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -10,50 +10,60 @@ import {ControlGroup} from '../model';
1010
import {Form} from './form_interface';
1111
import {Validators, NG_VALIDATORS} from '../validators';
1212

13-
const controlGroupBinding =
13+
const controlGroupProvider =
1414
CONST_EXPR(new Provider(ControlContainer, {useExisting: forwardRef(() => NgControlGroup)}));
1515

1616
/**
1717
* Creates and binds a control group to a DOM element.
1818
*
1919
* This directive can only be used as a child of {@link NgForm} or {@link NgFormModel}.
2020
*
21-
* ### Example
21+
* # Example ([live demo](http://plnkr.co/edit/7EJ11uGeaggViYM6T5nq?p=preview))
2222
*
23-
* In this example, we create the credentials and personal control groups.
24-
* We can work with each group separately: check its validity, get its value, listen to its changes.
25-
*
26-
* ```
23+
* ```typescript
2724
* @Component({
28-
* selector: "signup-comp",
29-
* directives: [FORM_DIRECTIVES],
30-
* template: `
31-
* <form #f="form" (submit)='onSignUp(f.value)'>
32-
* <div ng-control-group='credentials' #credentials="form">
33-
* Login <input type='text' ng-control='login'>
34-
* Password <input type='password' ng-control='password'>
35-
* </div>
36-
* <div *ng-if="!credentials.valid">Credentials are invalid</div>
37-
*
38-
* <div ng-control-group='personal'>
39-
* Name <input type='text' ng-control='name'>
40-
* </div>
41-
* <button type='submit'>Sign Up!</button>
42-
* </form>
43-
* `})
44-
* class SignupComp {
45-
* onSignUp(value) {
46-
* // value === {
47-
* // personal: {name: 'some name'},
48-
* // credentials: {login: 'some login', password: 'some password'}}
49-
* }
25+
* selector: 'my-app',
26+
* directives: [FORM_DIRECTIVES],
27+
* })
28+
* @View({
29+
* template: `
30+
* <div>
31+
* <h2>Angular2 Control &amp; ControlGroup Example</h2>
32+
* <form #f="form">
33+
* <div ng-control-group="name" #cg-name="form">
34+
* <h3>Enter your name:</h3>
35+
* <p>First: <input ng-control="first" required></p>
36+
* <p>Middle: <input ng-control="middle"></p>
37+
* <p>Last: <input ng-control="last" required></p>
38+
* </div>
39+
* <h3>Name value:</h3>
40+
* <pre>{{valueOf(cgName)}}</pre>
41+
* <p>Name is {{cgName?.control?.valid ? "valid" : "invalid"}}</p>
42+
* <h3>What's your favorite food?</h3>
43+
* <p><input ng-control="food"></p>
44+
* <h3>Form value</h3>
45+
* <pre>{{valueOf(f)}}</pre>
46+
* </form>
47+
* </div>
48+
* `,
49+
* directives: [FORM_DIRECTIVES]
50+
* })
51+
* export class App {
52+
* valueOf(cg: NgControlGroup): string {
53+
* if (cg.control == null) {
54+
* return null;
55+
* }
56+
* return JSON.stringify(cg.control.value, null, 2);
57+
* }
5058
* }
59+
* ```
5160
*
52-
* ```
61+
* This example declares a control group for a user's name. The value and validation state of
62+
* this group can be accessed separately from the overall form.
5363
*/
5464
@Directive({
5565
selector: '[ng-control-group]',
56-
bindings: [controlGroupBinding],
66+
providers: [controlGroupProvider],
5767
inputs: ['name: ng-control-group'],
5868
exportAs: 'form'
5969
})
@@ -75,10 +85,19 @@ export class NgControlGroup extends ControlContainer implements OnInit,
7585

7686
onDestroy(): void { this.formDirective.removeControlGroup(this); }
7787

88+
/**
89+
* Get the {@link ControlGroup} backing this binding.
90+
*/
7891
get control(): ControlGroup { return this.formDirective.getControlGroup(this); }
7992

93+
/**
94+
* Get the path to this control group.
95+
*/
8096
get path(): string[] { return controlPath(this.name, this._parent); }
8197

98+
/**
99+
* Get the {@link Form} to which this group belongs.
100+
*/
82101
get formDirective(): Form { return this._parent.formDirective; }
83102

84103
get validator(): Function { return Validators.compose(this._validators); }

modules/angular2/src/core/forms/directives/validators.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,16 @@ export interface Validator { validate(c: modelModule.Control): {[key: string]: a
2929
const REQUIRED_VALIDATOR =
3030
CONST_EXPR(new Provider(NG_VALIDATORS, {useValue: Validators.required, multi: true}));
3131

32+
/**
33+
* A Directive that adds the `required` validator to any controls marked with the
34+
* `required` attribute, via the {@link NG_VALIDATORS} binding.
35+
*
36+
* # Example
37+
*
38+
* ```
39+
* <input ng-control="fullName" required>
40+
* ```
41+
*/
3242
@Directive({
3343
selector: '[required][ng-control],[required][ng-form-control],[required][ng-model]',
3444
providers: [REQUIRED_VALIDATOR]

modules/angular2/src/core/forms/form_builder.ts

Lines changed: 29 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -7,63 +7,52 @@ import * as modelModule from './model';
77
/**
88
* Creates a form object from a user-specified configuration.
99
*
10-
* ### Example
11-
*
12-
* ```
13-
* import {Component, bootstrap} from 'angular2/angular2';
14-
* import {FormBuilder, Validators, FORM_DIRECTIVES, ControlGroup} from 'angular2/core';
10+
* ### Example ([live demo](http://plnkr.co/edit/ENgZo8EuIECZNensZCVr?p=preview))
1511
*
12+
* ```typescript
1613
* @Component({
17-
* selector: 'login-comp',
18-
* viewProviders: [FormBuilder],
14+
* selector: 'my-app',
15+
* viewBindings: [FORM_BINDINGS]
1916
* template: `
20-
* <form [control-group]="loginForm">
21-
* Login <input control="login">
22-
*
23-
* <div control-group="passwordRetry">
24-
* Password <input type="password" control="password">
25-
* Confirm password <input type="password" control="passwordConfirmation">
17+
* <form [ng-form-model]="loginForm">
18+
* <p>Login <input ng-control="login"></p>
19+
* <div ng-control-group="passwordRetry">
20+
* <p>Password <input type="password" ng-control="password"></p>
21+
* <p>Confirm password <input type="password" ng-control="passwordConfirmation"></p>
2622
* </div>
2723
* </form>
24+
* <h3>Form value:</h3>
25+
* <pre>{{value}}</pre>
2826
* `,
2927
* directives: [FORM_DIRECTIVES]
3028
* })
31-
* class LoginComp {
29+
* export class App {
3230
* loginForm: ControlGroup;
3331
*
3432
* constructor(builder: FormBuilder) {
3533
* this.loginForm = builder.group({
3634
* login: ["", Validators.required],
37-
*
3835
* passwordRetry: builder.group({
3936
* password: ["", Validators.required],
4037
* passwordConfirmation: ["", Validators.required]
4138
* })
4239
* });
4340
* }
44-
* }
45-
*
46-
* bootstrap(LoginComp);
47-
* ```
48-
*
49-
* This example creates a {@link ControlGroup} that consists of a `login` {@link Control}, and a
50-
* nested {@link ControlGroup} that defines a `password` and a `passwordConfirmation`
51-
* {@link Control}:
5241
*
42+
* get value(): string {
43+
* return JSON.stringify(this.loginForm.value, null, 2);
44+
* }
45+
* }
5346
* ```
54-
* var loginForm = builder.group({
55-
* login: ["", Validators.required],
56-
*
57-
* passwordRetry: builder.group({
58-
* password: ["", Validators.required],
59-
* passwordConfirmation: ["", Validators.required]
60-
* })
61-
* });
62-
*
63-
* ```
6447
*/
6548
@Injectable()
6649
export class FormBuilder {
50+
/**
51+
* Construct a new {@link ControlGroup} with the given map of configuration.
52+
* Valid keys for the `extra` parameter map are `optionals` and `validator`.
53+
*
54+
* See the {@link ControlGroup} constructor for more details.
55+
*/
6756
group(controlsConfig: {[key: string]: any},
6857
extra: {[key: string]: any} = null): modelModule.ControlGroup {
6958
var controls = this._reduceControls(controlsConfig);
@@ -77,6 +66,9 @@ export class FormBuilder {
7766
}
7867
}
7968

69+
/**
70+
* Construct a new {@link Control} with the given `value` and `validator`.
71+
*/
8072
control(value: Object, validator: Function = null): modelModule.Control {
8173
if (isPresent(validator)) {
8274
return new modelModule.Control(value, validator);
@@ -85,6 +77,10 @@ export class FormBuilder {
8577
}
8678
}
8779

80+
/**
81+
* Construct an array of {@link Control}s from the given `controlsConfig` array of
82+
* configuration, with the given optional `validator`.
83+
*/
8884
array(controlsConfig: any[], validator: Function = null): modelModule.ControlArray {
8985
var controls = controlsConfig.map(c => this._createControl(c));
9086
if (isPresent(validator)) {

0 commit comments

Comments
 (0)