Skip to content

Commit 4cd29f7

Browse files
committed
examples(forms): added an example of using model-driven forms
1 parent 3eff7be commit 4cd29f7

File tree

2 files changed

+168
-0
lines changed

2 files changed

+168
-0
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<!doctype html>
2+
<html>
3+
<head>
4+
<title>Model Driven Forms</title>
5+
<style>
6+
.ng-touched.ng-invalid {
7+
border-color: red;
8+
}
9+
</style>
10+
</head>
11+
12+
<body>
13+
<model-driven-forms>
14+
Loading...
15+
</model-driven-forms>
16+
17+
$SCRIPTS$
18+
</body>
19+
</html>
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
import {bootstrap, onChange, NgIf, Component, Directive, View, Ancestor} from 'angular2/angular2';
2+
import {
3+
formDirectives,
4+
ControlDirective,
5+
Validators,
6+
FormModelDirective,
7+
FormBuilder
8+
} from 'angular2/forms';
9+
10+
import {ObservableWrapper} from 'angular2/src/facade/async';
11+
import {RegExpWrapper, print, isPresent} from 'angular2/src/facade/lang';
12+
13+
import {reflector} from 'angular2/src/reflection/reflection';
14+
import {ReflectionCapabilities} from 'angular2/src/reflection/reflection_capabilities';
15+
16+
/**
17+
* Custom validator.
18+
*/
19+
function creditCardValidator(c): StringMap<string, boolean> {
20+
if (isPresent(c.value) && RegExpWrapper.test(new RegExp("^\\d{16}$"), c.value)) {
21+
return null;
22+
} else {
23+
return {"invalidCreditCard": true};
24+
}
25+
}
26+
27+
/**
28+
* This is a component that displays an error message.
29+
*
30+
* For instance,
31+
*
32+
* <show-error control="creditCard" [errors]="['required', 'invalidCreditCard']"></show-error>
33+
*
34+
* Will display the "is required" error if the control is empty, and "invalid credit card" if the
35+
* control is not empty
36+
* but not valid.
37+
*
38+
* In a real application, this component would receive a service that would map an error code to an
39+
* actual error message.
40+
* To make it simple, we are using a simple map here.
41+
*/
42+
@Component({selector: 'show-error', properties: ['controlPath: control', 'errorTypes: errors']})
43+
@View({
44+
template: `
45+
<span *ng-if="errorMessage !== null">{{errorMessage}}</span>
46+
`,
47+
directives: [NgIf]
48+
})
49+
class ShowError {
50+
formDir;
51+
controlPath: string;
52+
errorTypes: List<string>;
53+
54+
constructor(@Ancestor() formDir: FormModelDirective) { this.formDir = formDir; }
55+
56+
get errorMessage() {
57+
var c = this.formDir.form.find(this.controlPath);
58+
for (var i = 0; i < this.errorTypes.length; ++i) {
59+
if (isPresent(c) && c.touched && c.hasError(this.errorTypes[i])) {
60+
return this._errorMessage(this.errorTypes[i]);
61+
}
62+
}
63+
return null;
64+
}
65+
66+
_errorMessage(code) {
67+
var config = {'required': 'is required', 'invalidCreditCard': 'is invalid credit card number'};
68+
return config[code];
69+
}
70+
}
71+
72+
73+
@Component({selector: 'model-driven-forms', appInjector: [FormBuilder]})
74+
@View({
75+
template: `
76+
<h1>Checkout Form (Model Driven)</h1>
77+
78+
<form (ng-submit)="onSubmit()" [ng-form-model]="form" #f="form">
79+
<p>
80+
<label for="firstName">First Name</label>
81+
<input type="text" id="firstName" ng-control="firstName">
82+
<show-error control="firstName" [errors]="['required']"></show-error>
83+
</p>
84+
85+
<p>
86+
<label for="middleName">Middle Name</label>
87+
<input type="text" id="middleName" ng-control="middleName">
88+
</p>
89+
90+
<p>
91+
<label for="lastName">Last Name</label>
92+
<input type="text" id="lastName" ng-control="lastName">
93+
<show-error control="lastName" [errors]="['required']"></show-error>
94+
</p>
95+
96+
<p>
97+
<label for="creditCard">Credit Card</label>
98+
<input type="text" id="creditCard" ng-control="creditCard">
99+
<show-error control="creditCard" [errors]="['required', 'invalidCreditCard']"></show-error>
100+
</p>
101+
102+
<p>
103+
<label for="amount">Amount</label>
104+
<input type="number" id="amount" ng-control="amount">
105+
<show-error control="amount" [errors]="['required']"></show-error>
106+
</p>
107+
108+
<p>
109+
<label for="email">Email</label>
110+
<input type="email" id="email" ng-control="email">
111+
<show-error control="email" [errors]="['required']"></show-error>
112+
</p>
113+
114+
<p>
115+
<label for="comments">Comments</label>
116+
<textarea id="comments" ng-control="comments">
117+
</textarea>
118+
</p>
119+
120+
<button type="submit" [disabled]="!f.form.valid">Submit</button>
121+
</form>
122+
`,
123+
directives: [formDirectives, ShowError]
124+
})
125+
class ModelDrivenForms {
126+
form;
127+
128+
constructor(fb: FormBuilder) {
129+
this.form = fb.group({
130+
"firstName": ["", Validators.required],
131+
"middleName": [""],
132+
"lastName": ["", Validators.required],
133+
"creditCard": ["", Validators.compose([Validators.required, creditCardValidator])],
134+
"amount": [0, Validators.required],
135+
"email": ["", Validators.required],
136+
"comments": [""]
137+
});
138+
}
139+
140+
onSubmit() {
141+
print("Submitting:");
142+
print(this.form.value);
143+
}
144+
}
145+
146+
export function main() {
147+
reflector.reflectionCapabilities = new ReflectionCapabilities();
148+
bootstrap(ModelDrivenForms);
149+
}

0 commit comments

Comments
 (0)