Skip to content
This repository was archived by the owner on Dec 4, 2017. It is now read-only.

Commit 896334b

Browse files
Add reactive forms
1 parent d89a5ab commit 896334b

17 files changed

+814
-2
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<div class="container">
2+
<reactive-form></reactive-form>
3+
</div>
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/* tslint:disable:no-unused-variable */
2+
import { AppComponent } from './app.component';
3+
4+
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
5+
import { By } from '@angular/platform-browser';
6+
import { DebugElement } from '@angular/core';
7+
8+
//////// SPECS /////////////
9+
describe('AppComponent', function () {
10+
let de: DebugElement;
11+
let comp: AppComponent;
12+
let fixture: ComponentFixture<AppComponent>;
13+
14+
beforeEach(async(() => {
15+
TestBed.configureTestingModule({
16+
declarations: [ AppComponent ]
17+
})
18+
.compileComponents();
19+
}));
20+
21+
beforeEach(() => {
22+
fixture = TestBed.createComponent(AppComponent);
23+
comp = fixture.componentInstance;
24+
de = fixture.debugElement.query(By.css('h1'));
25+
});
26+
27+
it('should create component', () => expect(comp).toBeDefined() );
28+
29+
it('should have expected <h1> text', () => {
30+
fixture.detectChanges();
31+
const h1 = de.nativeElement;
32+
expect(h1.innerText).toMatch(/angular/i,
33+
'<h1> should say something about "Angular"');
34+
});
35+
});
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { Component } from '@angular/core';
2+
import { ReactiveFormComponent } from './reactive-form.component';
3+
4+
@Component({
5+
moduleId: module.id,
6+
selector: 'my-app',
7+
templateUrl: './app.component.html'
8+
})
9+
export class AppComponent { }
10+
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { NgModule } from '@angular/core';
2+
import { BrowserModule } from '@angular/platform-browser';
3+
4+
import { AppComponent } from './app.component';
5+
6+
import { ReactiveFormsModule } from '@angular/forms';
7+
import { ReactiveFormComponent } from './reactive-form.component';
8+
9+
@NgModule({
10+
imports: [
11+
BrowserModule,
12+
ReactiveFormsModule
13+
],
14+
declarations: [
15+
AppComponent,
16+
ReactiveFormComponent
17+
],
18+
bootstrap: [ AppComponent ]
19+
})
20+
export class AppModule { }
Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
<!-- #docplaster -->
2+
<!-- #docregion final -->
3+
<div class="container">
4+
<!-- #docregion edit-div -->
5+
<div [hidden]="submitted">
6+
<h1>Hero Form</h1>
7+
<!-- #docregion ngSubmit -->
8+
<form *ngIf="active" (ngSubmit)="onSubmit()" #heroForm="ngForm">
9+
<!-- #enddocregion ngSubmit -->
10+
<!-- #enddocregion edit-div -->
11+
<div class="form-group">
12+
<!-- #docregion name-with-error-msg -->
13+
<label for="name">Name</label>
14+
<input type="text" class="form-control" id="name"
15+
required
16+
[(ngModel)]="model.name" name="name"
17+
#name="ngModel" >
18+
<!-- #docregion hidden-error-msg -->
19+
<div [hidden]="name.valid || name.pristine"
20+
class="alert alert-danger">
21+
<!-- #enddocregion hidden-error-msg -->
22+
Name is required
23+
</div>
24+
<!-- #enddocregion name-with-error-msg -->
25+
</div>
26+
27+
<div class="form-group">
28+
<label for="alterEgo">Alter Ego</label>
29+
<input type="text" class="form-control" id="alterEgo"
30+
[(ngModel)]="model.alterEgo" name="alterEgo" >
31+
</div>
32+
33+
<div class="form-group">
34+
<label for="power">Hero Power</label>
35+
<select class="form-control" id="power"
36+
required
37+
[(ngModel)]="model.power" name="power"
38+
#power="ngModel" >
39+
<option *ngFor="let p of powers" [value]="p">{{p}}</option>
40+
</select>
41+
<div [hidden]="power.valid || power.pristine" class="alert alert-danger">
42+
Power is required
43+
</div>
44+
</div>
45+
46+
<!-- #docregion submit-button -->
47+
<button type="submit" class="btn btn-default" [disabled]="!heroForm.form.valid">Submit</button>
48+
<!-- #enddocregion submit-button -->
49+
50+
<!-- #docregion new-hero-button -->
51+
<button type="button" class="btn btn-default" (click)="newHero()">New Hero</button>
52+
<!-- #enddocregion new-hero-button -->
53+
54+
<!-- #enddocregion final -->
55+
<!-- NOT SHOWN IN DOCS -->
56+
<div>
57+
<hr>
58+
Name via form.controls = {{showFormControls(heroForm)}}
59+
</div>
60+
<!-- - -->
61+
<!-- #docregion final -->
62+
</form>
63+
</div>
64+
65+
<!-- #docregion submitted -->
66+
<div [hidden]="!submitted">
67+
<h2>You submitted the following:</h2>
68+
<div class="row">
69+
<div class="col-xs-3">Name</div>
70+
<div class="col-xs-9 pull-left">{{ model.name }}</div>
71+
</div>
72+
<div class="row">
73+
<div class="col-xs-3">Alter Ego</div>
74+
<div class="col-xs-9 pull-left">{{ model.alterEgo }}</div>
75+
</div>
76+
<div class="row">
77+
<div class="col-xs-3">Power</div>
78+
<div class="col-xs-9 pull-left">{{ model.power }}</div>
79+
</div>
80+
<br>
81+
<button class="btn btn-default" (click)="submitted=false">Edit</button>
82+
</div>
83+
<!-- #enddocregion submitted -->
84+
</div>
85+
<!-- #enddocregion final -->
86+
87+
<!-- ==================================================== -->
88+
<div>
89+
<form>
90+
<!-- #docregion edit-div -->
91+
92+
<!-- ... all of the form ... -->
93+
94+
</form>
95+
</div>
96+
<!-- #enddocregion edit-div -->
97+
98+
<!-- ==================================================== -->
99+
<hr>
100+
<style>
101+
.no-style .ng-valid {
102+
border-left: 1px solid #CCC
103+
}
104+
105+
.no-style .ng-invalid {
106+
border-left: 1px solid #CCC
107+
}
108+
</style>
109+
<div class="no-style" style="margin-left: 4px">
110+
<!-- #docregion start -->
111+
<div class="container">
112+
<h1>Hero Form</h1>
113+
<form>
114+
<div class="form-group">
115+
<label for="name">Name</label>
116+
<input type="text" class="form-control" id="name" required>
117+
</div>
118+
119+
<div class="form-group">
120+
<label for="alterEgo">Alter Ego</label>
121+
<input type="text" class="form-control" id="alterEgo">
122+
</div>
123+
124+
<!-- #enddocregion start -->
125+
<!-- #docregion powers -->
126+
<div class="form-group">
127+
<label for="power">Hero Power</label>
128+
<select class="form-control" id="power" required>
129+
<option *ngFor="let p of powers" [value]="p">{{p}}</option>
130+
</select>
131+
</div>
132+
133+
<!-- #enddocregion powers -->
134+
<!-- #docregion start -->
135+
<button type="submit" class="btn btn-default">Submit</button>
136+
137+
</form>
138+
</div>
139+
<!-- #enddocregion start -->
140+
<!-- #enddocregion phase1-->
141+
142+
<!-- ==================================================== -->
143+
<hr>
144+
<!-- #docregion phase2-->
145+
<div class="container">
146+
<h1>Hero Form</h1>
147+
<form>
148+
<!-- #docregion ngModel-2-->
149+
{{diagnostic}}
150+
<div class="form-group">
151+
<label for="name">Name</label>
152+
<input type="text" class="form-control" id="name"
153+
required
154+
[(ngModel)]="model.name" name="name">
155+
</div>
156+
157+
<div class="form-group">
158+
<label for="alterEgo">Alter Ego</label>
159+
<input type="text" class="form-control" id="alterEgo"
160+
[(ngModel)]="model.alterEgo" name="alterEgo">
161+
</div>
162+
163+
<div class="form-group">
164+
<label for="power">Hero Power</label>
165+
<select class="form-control" id="power"
166+
required
167+
[(ngModel)]="model.power" name="power">
168+
<option *ngFor="let p of powers" [value]="p">{{p}}</option>
169+
</select>
170+
</div>
171+
172+
<!-- #enddocregion ngModel-2-->
173+
<button type="submit" class="btn btn-default">Submit</button>
174+
175+
</form>
176+
</div>
177+
<!-- #enddocregion phase2-->
178+
179+
<!-- EXTRA MATERIAL FOR DOCUMENTATION -->
180+
<hr>
181+
<!-- #docregion ngModel-1-->
182+
<input type="text" class="form-control" id="name"
183+
required
184+
[(ngModel)]="model.name" name="name">
185+
TODO: remove this: {{model.name}}
186+
<!-- #enddocregion ngModel-1-->
187+
<hr>
188+
<!-- #docregion ngModel-3-->
189+
<input type="text" class="form-control" id="name"
190+
required
191+
[ngModel]="model.name" name="name"
192+
(ngModelChange)="model.name = $event" >
193+
TODO: remove this: {{model.name}}
194+
<!-- #enddocregion ngModel-3-->
195+
<hr>
196+
<!-- #docregion form-active -->
197+
<form *ngIf="active">
198+
<!-- #enddocregion form-active -->
199+
200+
<!-- #docregion ngModelName-1 -->
201+
<input type="text" class="form-control" id="name"
202+
required
203+
[(ngModel)]="model.name" name="name" >
204+
<!-- #enddocregion ngModelName-1 -->
205+
<hr>
206+
<!-- #docregion ngModelName-2 -->
207+
<input type="text" class="form-control" id="name"
208+
required
209+
[(ngModel)]="model.name" name="name"
210+
#spy >
211+
<br>TODO: remove this: {{spy.className}}
212+
<!-- #enddocregion ngModelName-2 -->
213+
</form>
214+
215+
</div>
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// #docplaster
2+
// #docregion
3+
// #docregion first, final
4+
import { Component } from '@angular/core';
5+
6+
import { Hero } from './hero';
7+
8+
@Component({
9+
moduleId: module.id,
10+
selector: 'hero-form',
11+
templateUrl: 'hero-form.component.html'
12+
})
13+
export class HeroFormComponent {
14+
15+
powers = ['Really Smart', 'Super Flexible',
16+
'Super Hot', 'Weather Changer'];
17+
18+
model = new Hero(18, 'Dr IQ', this.powers[0], 'Chuck Overstreet');
19+
20+
// #docregion submitted
21+
submitted = false;
22+
23+
onSubmit() { this.submitted = true; }
24+
// #enddocregion submitted
25+
26+
// #enddocregion final
27+
// TODO: Remove this when we're done
28+
get diagnostic() { return JSON.stringify(this.model); }
29+
// #enddocregion first
30+
31+
// #docregion final
32+
// Reset the form with a new hero AND restore 'pristine' class state
33+
// by toggling 'active' flag which causes the form
34+
// to be removed/re-added in a tick via NgIf
35+
// TODO: Workaround until NgForm has a reset method (#6822)
36+
// #docregion new-hero
37+
active = true;
38+
39+
// #docregion new-hero-v1
40+
newHero() {
41+
this.model = new Hero(42, '', '');
42+
// #enddocregion new-hero-v1
43+
this.active = false;
44+
setTimeout(() => this.active = true, 0);
45+
// #docregion new-hero-v1
46+
}
47+
// #enddocregion new-hero-v1
48+
// #enddocregion new-hero
49+
// #enddocregion final
50+
//////// NOT SHOWN IN DOCS ////////
51+
52+
// Reveal in html:
53+
// Name via form.controls = {{showFormControls(heroForm)}}
54+
showFormControls(form: any) {
55+
56+
return form && form.controls['name'] &&
57+
// #docregion form-controls
58+
form.controls['name'].value; // Dr. IQ
59+
// #enddocregion form-controls
60+
}
61+
62+
/////////////////////////////
63+
64+
// #docregion first, final
65+
}
66+
// #enddocregion first, final
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// #docregion
2+
export class Hero {
3+
4+
constructor(
5+
public id: number,
6+
public name: string,
7+
public power: string,
8+
public alterEgo?: string
9+
) { }
10+
11+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
2+
3+
import { AppModule } from './app.module';
4+
5+
platformBrowserDynamic().bootstrapModule(AppModule);

0 commit comments

Comments
 (0)