@@ -56,11 +56,6 @@ a#intro
5656 the form controls and pull user-changed values back out. The component can
5757 observe changes in form control state and react to those changes.
5858
59- One advantage of working with the form control objects directly is that
60- value and validity updates are always synchronous. This contrasts with
61- template-driven forms, which must update asynchronously because they
62- delegate operations to a directive running in the template.
63-
6459 In keeping with the reactive paradigm, the component
6560 preserves the immutability of the _data model_,
6661 treating it as a pure source of original values.
@@ -133,7 +128,7 @@ a#create-component
133128 Make a new file called
134129 `hero-detail.component.ts` in the `app` directory and import these symbols:
135130
136- + makeExample('reactive-forms/ts/app/hero-detail.component.ts' , 'reactive-comp- imports' ,'app/hero-detail.component.ts' )( format ="." )
131+ + makeExample('reactive-forms/ts/app/hero-detail-1 .component.ts' , 'imports' ,'app/hero-detail.component.ts' )( format ="." )
137132
138133:marked
139134 Now enter the `@Component` decorator that specifies the `HeroDetailComponent` metadata:
@@ -146,8 +141,12 @@ a#create-component
146141 such as when specifying the `templateUrl`.
147142
148143 Next, create an exported `HeroDetailComponent` class with a `FormControl`.
144+ Notice that the `FormControl` is within a `FormGroup`. While you don't
145+ _have_ to put a `FormControl` in a `FormGroup` for it to work, forms
146+ usually contain multiple controls and grouping them offers advantages
147+ you'll learn later in this guide.
149148
150- + makeExample('reactive-forms/ts/app/hero-detail-versions .component.ts' , 'v1' ,'app/hero-detail.component.ts (excerpt)' )( format ="." )
149+ + makeExample('reactive-forms/ts/app/hero-detail-1 .component.ts' , 'v1' ,'app/hero-detail.component.ts (excerpt)' )( format ="." )
151150
152151:marked
153152 Here you are creating a `FormGroup` called `heroForm` with a child `FormControl` called `name`.
@@ -161,8 +160,8 @@ a#create-component
161160
162161.l-sub-section
163162 :marked
164- Validators won't be covered at all in this guide.
165- Learn about them in the [Form Validation](../cookbook/form-validation.html) cookbook.
163+ Validators aren't covered at all in this guide.
164+ Read about them in the [Form Validation](../cookbook/form-validation.html) cookbook.
166165
167166.l-main-section
168167a#create-template
@@ -287,7 +286,10 @@ a#formbuilder
287286 The `FormBuilder` class helps reduce repetition and
288287 clutter by handling details of control creation for you.
289288
290- You already imported `FormBuilder` into `hero-detail.component.ts`.
289+ To use `FormBuilder`, you need to import it into `hero-detail.component.ts`:
290+ + makeExample('reactive-forms/ts/app/hero-detail-2.component.ts' , 'imports' ,'app/hero-detail.component.ts (excerpt)' )( format ="." )
291+
292+ :marked
291293 Use it now to refactor the `HeroDetailComponent` into something that's a little easier to read and write,
292294 by following this plan:
293295
@@ -297,7 +299,7 @@ a#formbuilder
297299 * Call `createForm` in the constructor.
298300
299301 The revised `HeroDetailComponent` looks like this:
300- + makeExample('reactive-forms/ts/app/hero-detail-versions .component.ts' , 'v2' ,'app/hero-detail.component.ts (excerpt)' )( format ="." )
302+ + makeExample('reactive-forms/ts/app/hero-detail-2 .component.ts' , 'v2' ,'app/hero-detail.component.ts (excerpt)' )( format ="." )
301303
302304:marked
303305 `FormBuilder.group` is a factory method that creates a `FormGroup`.
@@ -309,10 +311,17 @@ a#formbuilder
309311
310312:marked
311313 ### More FormControls
312- A hero has more than a name. A hero has an address too.
313- Add some address `FormControls` to the `heroForm` as follows.
314+ A hero has more than a name. A hero has an address too. You already have address data
315+ in `data-model.ts`, so add it to the imports so you can use it:
314316
315- + makeExample('reactive-forms/ts/app/hero-detail-versions.component.ts' , 'v3' ,'app/hero-detail.component.ts (excerpt)' )( format ="." )
317+ + makeExample('reactive-forms/ts/app/hero-detail-3.component.ts' , 'imports' ,'app/hero-detail.component.ts (excerpt)' )( format ="." )
318+
319+ :marked
320+ Add some address `FormControls` to the `heroForm` as follows, being sure to
321+ also declare `states`. This allows you to populate the state select with
322+ the states in `data-model.ts`.
323+
324+ + makeExample('reactive-forms/ts/app/hero-detail-3.component.ts' , 'v3' ,'app/hero-detail.component.ts (excerpt)' )( format ="." )
316325
317326:marked
318327 Then add corresponding markup in `hero-detail.component.html`
@@ -344,7 +353,7 @@ a#grouping
344353 Let that be the parent `FormGroup`.
345354 Use `FormBuilder` again to create a child `FormGroup` that encapsulates the address controls;
346355 assign the result to a new `address` property of the parent `FormGroup`.
347- + makeExample('reactive-forms/ts/app/hero-detail-versions .component.ts' , 'v4' ,'app/hero-detail.component.ts (excerpt)' )( format ="." )
356+ + makeExample('reactive-forms/ts/app/hero-detail-4 .component.ts' , 'v4' ,'app/hero-detail.component.ts (excerpt)' )( format ="." )
348357
349358:marked
350359 You’ve changed the structure of the form controls in the component class;
@@ -464,7 +473,7 @@ a#data-model-form-model
464473:marked
465474 Here, again, is the component's `FormGroup` definition.
466475
467- + makeExample('reactive-forms/ts/app/hero-detail-versions .component.ts' , 'hero-form-model' ,'app/hero-detail.component.ts (excerpt)' )( format ="." )
476+ + makeExample('reactive-forms/ts/app/hero-detail-5 .component.ts' , 'hero-form-model' ,'app/hero-detail.component.ts (excerpt)' )( format ="." )
468477:marked
469478 There are two significant differences between these models:
470479
@@ -478,8 +487,16 @@ a#data-model-form-model
478487
479488:marked
480489 Take a moment to refactor the _address_ `FormGroup` definition for brevity and clarity as follows:
481- + makeExample('reactive-forms/ts/app/hero-detail-versions.component.ts' , 'address-form-group' )( format ="." )
490+ + makeExample('reactive-forms/ts/app/hero-detail-6.component.ts' , 'address-form-group' )( format ="." )
491+
482492:marked
493+ Also be sure to update the imports so that you can use the `Hero` object:
494+ + makeExample('reactive-forms/ts/app/hero-detail-5.component.ts' , 'imports' )( format ="." )
495+
496+ :marked
497+ # Ward, `hero-detail-5.component.ts` is where `@Input() hero: Hero;`
498+ # shows up for the first time, but I don't understand it or know where
499+ # I should mention it. It seems like this is the general area, but we don't demonstrate it.
483500
484501.l-main-section
485502a#set-data
@@ -493,7 +510,7 @@ a#set-data
493510 With **`setValue`**, you assign _every_ form control value _at once_
494511 by passing in a data object whose properties exactly match the _form model_ behind the `FormGroup`.
495512
496- + makeExample('reactive-forms/ts/app/hero-detail-versions .component.ts' , 'set-value' ,'app/hero-detail.component.ts (excerpt)' )( format ="." )
513+ + makeExample('reactive-forms/ts/app/hero-detail-6 .component.ts' , 'set-value' ,'app/hero-detail.component.ts (excerpt)' )( format ="." )
497514:marked
498515 The `setValue` method checks the data object thoroughly before assigning any form control values.
499516
@@ -509,15 +526,15 @@ a#set-data
509526
510527 You can only show the hero's first address and you must account for the possibility that the `hero` has no addresses at all.
511528 This explains the conditional setting of the `address` property in the data object argument:
512- + makeExample('reactive-forms/ts/app/hero-detail-versions .component.ts' , 'set-value-address' )( format ="." )
529+ + makeExample('reactive-forms/ts/app/hero-detail-6 .component.ts' , 'set-value-address' )( format ="." )
513530
514531:marked
515532 ### _patchValue_
516533 With **`patchValue`**, you can assign values to specific controls in a `FormGroup`
517534 by supplying an object of key/value pairs for just the controls of interest.
518535
519536 This example sets only the form's `name` control.
520- + makeExample('reactive-forms/ts/app/hero-detail-versions .component.ts' , 'patch-value' ,'app/hero-detail.component.ts (excerpt)' )( format ="." )
537+ + makeExample('reactive-forms/ts/app/hero-detail-5 .component.ts' , 'patch-value' ,'app/hero-detail.component.ts (excerpt)' )( format ="." )
521538
522539:marked
523540 With **`patchValue`** you have more flexibility to cope with wildly divergent data and form models.
@@ -558,9 +575,15 @@ a#set-data
558575 control values from the previous hero are cleared and
559576 status flags are restored to the _pristine_ state.
560577
578+ In order to use `ngOnChanges`, add it to the `hero-detail.component.ts`
579+ imports.
580+
581+ + makeExample('reactive-forms/ts/app/hero-detail-5.component.ts' , 'imports' ,'app/hero-detail.component.ts (excerpt)' )( format ="." )
582+
583+ :marked
561584 Here's what `ngOnChanges` should look like:
562585
563- + makeExample('reactive-forms/ts/app/hero-detail-versions .component.ts' , 'set-value-on-changes' ,'app/hero-detail.component.ts (excerpt)' )( format ="." )
586+ + makeExample('reactive-forms/ts/app/hero-detail-6 .component.ts' , 'set-value-on-changes' ,'app/hero-detail.component.ts (excerpt)' )( format ="." )
564587
565588a#hero-list
566589:marked
@@ -611,7 +634,11 @@ a#form-array
611634 An _address_ `FormGroup` can display one `Address`.
612635 An Angular `FormArray` can display an array of _address_ `FormGroups`.
613636
614- To work with a `FormArray` you do the following:
637+ To get access to the `FormArray` class, import it into `hero-detail.component.ts`:
638+ + makeExample('reactive-forms/ts/app/hero-detail-7.component.ts' , 'imports' ,'app/hero-detail.component.ts (excerpt)' )( format ="." )
639+
640+ :marked
641+ To _work_ with a `FormArray` you do the following:
615642 1. Define the items (`FormControls` or `FormGroups`) in the array.
616643 1. Initialize the array with items created from data in the _data model_.
617644 1. Add and remove items as the user requires.
@@ -621,15 +648,15 @@ a#form-array
621648
622649 You’ll need to redefine the form model in the `HeroDetailComponent` constructor,
623650 which currently only displays the first hero address in an _address_ `FormGroup`.
624- + makeExample('reactive-forms/ts/app/hero-detail-versions .component.ts' , 'address-form-group' )( format ="." )
651+ + makeExample('reactive-forms/ts/app/hero-detail-6 .component.ts' , 'address-form-group' )( format ="." )
625652
626653:marked
627654 ### From _address_ to _secret lairs_
628655
629656 From the user's point of view, heroes don't have _addresses_.
630657 _Addresses_ are for mere mortals. Heroes have _secret lairs_!
631658 Replace the _address_ `FormGroup` definition with a _secretLairs_ `FormArray` definition:
632- + makeExample('reactive-forms/ts/app/hero-detail-versions .component.ts' , 'secretLairs-form-array' )( format ="." )
659+ + makeExample('reactive-forms/ts/app/hero-detail-7 .component.ts' , 'secretLairs-form-array' )( format ="." )
633660
634661.alert.is-helpful
635662 :marked
@@ -652,7 +679,7 @@ a#form-array
652679
653680 The following method replaces the _secretLairs_ `FormArray` with a new `FormArray`,
654681 initialized by an array of hero address `FormGroups`.
655- + makeExample('reactive-forms/ts/app/hero-detail-versions .component.ts' , 'set-addresses' )( format ="." )
682+ + makeExample('reactive-forms/ts/app/hero-detail-7 .component.ts' , 'set-addresses' )( format ="." )
656683
657684:marked
658685 Notice that you replace the previous `FormArray` with the **`FormGroup.setControl` method**, not with `setValue`.
@@ -665,7 +692,7 @@ a#form-array
665692
666693 Use the `FormGroup.get` method to acquire a reference to that `FormArray`.
667694 Wrap the expression in a `secretLairs` convenience property for clarity and re-use.
668- + makeExample('reactive-forms/ts/app/hero-detail-versions .component.ts' , 'get-secret-lairs' ,'app/hero-detail.component.ts (secretLayers property)' )( format ="." )
695+ + makeExample('reactive-forms/ts/app/hero-detail-7 .component.ts' , 'get-secret-lairs' ,'app/hero-detail.component.ts (secretLayers property)' )( format ="." )
669696
670697:marked
671698 ### Display the _FormArray_
@@ -699,7 +726,7 @@ a#form-array
699726 ### Add a new lair to the _FormArray_
700727
701728 Add an `addLair` method that gets the _secretLairs_ `FormArray` and appends a new _address_ `FormGroup` to it.
702- + makeExample('reactive-forms/ts/app/hero-detail-versions .component.ts' , 'add-lair' ,'app/hero-detail.component.ts (addLair method)' )( format ="." )
729+ + makeExample('reactive-forms/ts/app/hero-detail-7 .component.ts' , 'add-lair' ,'app/hero-detail.component.ts (addLair method)' )( format ="." )
703730
704731:marked
705732 Place a button on the form so the user can add a new _secret lair_ and wire it to the component's `addLair` method.
@@ -807,7 +834,7 @@ figure.image-display
807834 Instead, it must prepare `saveHero` whose values derive from a combination of original hero values (the `hero.id`)
808835 and deep copies of the potentially-changed form model values.
809836
810- #Ward, stop lecturing#
837+ # Ward, stop lecturing :D
811838
812839+ makeExample('reactive-forms/ts/app/hero-detail.component.ts' , 'prepare-save-hero' ,'app/hero-detail.component.ts (prepareSaveHero)' )( format ="." )
813840
0 commit comments