@@ -56,16 +56,9 @@ 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- In keeping with the reactive paradigm, the component
60- preserves the immutability of the _data model_,
61- treating it as a pure source of original values.
62- Rather than update the data model directly,
63- the component extracts user changes and forwards them to an external component or service,
64- which does something with them (such as saving them)
65- and returns a new _data model_ to the component that reflects the updated model state.
66-
67- Using reactive form directives does not require you to follow all reactive priniciples,
68- but it does facilitate the reactive programming approach should you choose to use it.
59+ One advantage of working with form control objects directly is that value and validity updates
60+ are always synchronous and under your control.
61+ You won't encounter the timing issues that sometimes plague a template-driven form.
6962
7063 ### _Template-driven_ forms
7164
@@ -542,55 +535,48 @@ a#set-data
542535
543536 Now you know _how_ to set the _form model_ values. But _when_ do you set them?
544537 The answer depends upon when the component gets the _data model_ values.
545-
546- If the `HeroDetailComponent` is editing a _new_ hero, the data model consists entirely of default values
547- that you could copy to the `FormControls` when you create them in the component's constructor.
548- That's effectively what you did when you set each control to the empty string.
549-
550- If the `HeroDetailComponent` is editing an _existing_ hero, you have to wait for that hero to arrive.
551- The component _might_ have the ability to retrieve the hero from the server (via an injected data service)
552- in which case you could set the form model in the [ngOnInit](lifecyle-hooks.html#oninit) lifecycle hook.
553- The final version of the `HeroDetailComponent` in the [Tour of Heroes](../tutorial/toh-pt6.html) does it this way.
554538
555- The `HeroDetailComponent` in this reactive forms sample works a little differently.
556- It's the _detail_ view nested within a _master/detail_ `HeroListComponent` ([discussed below](#hero-list)).
557-
539+ The `HeroDetailComponent` in this reactive forms sample is nested within a _master/detail_ `HeroListComponent` ([discussed below](#hero-list)).
558540 The `HeroListComponent` displays hero names to the user.
559541 When the user clicks on a hero, the list component passes the selected hero into the `HeroDetailComponent`
560- by ** binding to the latter's `hero` input property** .
542+ by binding to its `hero` input property.
561543
562544+ makeExample('reactive-forms/ts/app/hero-list.component.1.html' , '' ,'hero-list.component.html (simplified)' )( format ="." )
563545
564546:marked
565547 In this approach, the value of `hero` in the `HeroDetailComponent` changes
566548 every time the user selects a new hero.
567- You can't call _setValue_ in `ngOnInit` or you'll miss the user's selections.
568- Put the _setValue_ logic in the [ngOnChanges](lifecyle-hooks.html#onchanges)
569- hook, which Angular calls whenever the input `hero` property changes .
549+ You should call _setValue_ in the [ngOnChanges](lifecyle-hooks.html#onchanges)
550+ hook, which Angular calls whenever the input `hero` property changes
551+ as the following steps demonstrate .
570552
571- You should also _reset the form_ when the hero changes so that
572- control values from the previous hero are cleared and
573- status flags are restored to the _pristine_ state.
553+ First, import the `ngOnChanges` and `import` symbol in `hero-detail.component.ts`.
574554
575- In order to use `ngOnChanges`, add it to the `hero-detail.component.ts`
576- imports.
555+ + makeExample('reactive-forms/ts/app/hero-detail-5.component.ts' , 'import-input' ,'app/hero-detail.component.ts (core imports)' )( format ="." )
577556
578- + makeExample('reactive-forms/ts/app/hero-detail-5.component.ts' , 'imports' ,'app/hero-detail.component.ts (excerpt)' )( format ="." )
557+ :marked
558+ Add the `hero` input property.
559+ + makeExample('reactive-forms/ts/app/hero-detail-5.component.ts' , 'hero' )( format ="." )
579560
580561:marked
581- Here's what `ngOnChanges` should look like :
562+ Add the `ngOnChanges` method to the class as follows :
582563
583- + makeExample('reactive-forms/ts/app/hero-detail-6.component.ts' , 'set-value-on-changes ' ,'app/hero-detail.component.ts (excerpt )' )( format ="." )
564+ + makeExample('reactive-forms/ts/app/hero-detail-6.component.ts' , 'ngOnChanges-1 ' ,'app/hero-detail.component.ts (ngOnchanges )' )( format ="." )
584565
585566:marked
586- You could, however, reset the value of the *formControls* in the `reset()`
587- method by refactoring.
588- ## Ward, are the benefits that now you can dispense with `setValue` (so less code
589- ## and you don't have to set everything)? In `hero-detail-7.component.ts`, we also have
590- ## `this.setAddresses(this.hero.addresses);` in `ngOnChanges`.
591- ## Do I need to include it and talk about it?
567+ ### _reset_ the form flags
568+
569+ You should reset the form when the hero changes so that
570+ control values from the previous hero are cleared and
571+ status flags are restored to the _pristine_ state.
572+ You could call `reset` at the top of `ngOnChanges` like this.
573+ + makeExample('reactive-forms/ts/app/hero-detail-6.component.ts' , 'reset' )( format ="." )
592574
593- + makeExample('reactive-forms/ts/app/hero-detail-7.component.ts' , 'reset-refactor' ,'app/hero-detail.component.ts (excerpt)' )( format ="." )
575+ :marked
576+ The `reset` method has an optional `state` value so you can reset the flags _and_ the control values at the same.
577+ Internally, `reset` passes the argument to `setValue`.
578+ A little refactoring and `ngOnChanges` becomes this:
579+ + makeExample('reactive-forms/ts/app/hero-detail-6.component.ts' , 'ngOnChanges' , 'app/hero-detail.component.ts (ngOnchanges - revised)' )( format ="." )
594580
595581a#hero-list
596582:marked
@@ -611,12 +597,11 @@ figure.image-display
611597
612598 When the user clicks on a hero,
613599 the component sets its `selectedHero` property which
614- is ** bound to the `hero` input property** of the `HeroDetailComponent`.
600+ is bound to the `hero` input property of the `HeroDetailComponent`.
615601 The `HeroDetailComponent` detects the changed hero and re-sets its form
616602 with that hero's data values.
617603
618604 A "Refresh" button clears the hero list and the current selected hero before refetching the heroes.
619- The `HeroListComponent` also has an `onSave` method that you'll wire up later in this guide.
620605
621606 The remaining `HeroListComponent` and `HeroService` implementation details are not relevant to understanding reactive forms.
622607 The techniques involved are covered elsewhere in the documentation, including the _Tour of Heroes_
@@ -684,7 +669,7 @@ a#form-array
684669 You need a method to populate (or repopulate) the _secretLairs_ with actual hero addresses whenever
685670 the parent `HeroListComponent` sets the `HeroListComponent.hero` input property to a new `Hero`.
686671
687- The following method replaces the _secretLairs_ `FormArray` with a new `FormArray`,
672+ The following `setAddresses` method replaces the _secretLairs_ `FormArray` with a new `FormArray`,
688673 initialized by an array of hero address `FormGroups`.
689674+ makeExample('reactive-forms/ts/app/hero-detail-7.component.ts' , 'set-addresses' )( format ="." )
690675
@@ -780,9 +765,9 @@ a#observe-control
780765 that raises a change event.
781766
782767 These are properties, such as `valueChanges`, that return an RxJS `Observable`.
783- You don't need to know much about RxJS `Observable` to watch for a form control value change .
768+ You don't need to know much about RxJS `Observable` to monitor form control values .
784769
785- Add the following method to watch for changes to the value of the _name_ `FormControl`.
770+ Add the following method to log changes to the value of the _name_ `FormControl`.
786771+ makeExample('reactive-forms/ts/app/hero-detail.component.ts' , 'log-name-change' ,'app/hero-detail.component.ts (logNameChange)' )( format ="." )
787772
788773:marked
@@ -819,53 +804,33 @@ figure.image-display
819804
820805:marked
821806 ### Save
822- In this sample application, the `HeroDetailComponent` cannot perform the save operation.
823- The component delegates that chore to its parent `HeroListComponent`.
824-
825- When the user clicks the _Save_ button, the `HeroDetailComponent` raises a save event on its `save` output property.
826- The parent `HeroListComponent`, which binds to that property, responds to the event and processes the event payload.
827- + makeExample('reactive-forms/ts/app/hero-list.component.html' , 'hero-binding' ,'app/hero-list.component.html (save event binding)' )( format ="." )
828- :marked
829- The save event payload _could_ have any shape but often it's in the shape of the data model and that is the case in this example.
830- + makeExample('reactive-forms/ts/app/hero-detail.component.ts' , 'save-emitter' )( format ="." )
831-
832- :marked
833- The `HeroDetailComponent` save method (`onSubmit`) constructs a `saveHero`
834- and emits a save message, with `saveHero` as the payload, for the `HeroListComponent` to process.
835-
807+ In this sample application, when the user submits the form,
808+ the `HeroDetailComponent` will pass an instance of the hero _data model_
809+ to a save method on the injected `HeroService`.
836810+ makeExample('reactive-forms/ts/app/hero-detail.component.ts' , 'on-submit' ,'app/hero-detail.component.ts (onSubmit)' )( format ="." )
837811:marked
838- In the reactive paradigm, the _data model_ is immutable so the save method can't update the component's `hero`
839- and send that as the save event payload.
840-
841- Instead, it must prepare `saveHero` whose values derive from a combination of original hero values (the `hero.id`)
842- and deep copies of the potentially-changed form model values.
843-
844- ## Ward, stop lecturing :D
812+ This original `hero` had the pre-save values. The user's changes are still in the _form model_.
813+ So you create a new `hero` from a combination of original hero values (the `hero.id`)
814+ and deep copies of the changed form model values, using the `prepareSaveHero` helper.
845815
846816+ makeExample('reactive-forms/ts/app/hero-detail.component.ts' , 'prepare-save-hero' ,'app/hero-detail.component.ts (prepareSaveHero)' )( format ="." )
847817
848- :marked
849- In the reactive paradigm, the form model and its object contents must not leak out of the component.
850- The `saveHero` in the event payload must be completely disconnected from the form model.
851- Ideally, it is as immutable as the component's source `hero`.
852-
853- If you assign the `formModel.secretLairs` to `saveHero.addresses` (see line commented out),
854- the addresses in the `saveHero.addresses` array will be the same objects
855- as the lairs in the `formModel.secretLairs`.
856- A user's subsequent changes to a lair street will mutate an address street in the `saveHero`.
857- The `prepareSaveHero` method makes copies of the form model's `secretLairs` objects so that can't happen.
818+ .l-sub-section
819+ :marked
820+ **Address deep copy**
858821
859- Keeping data immutable takes effort and vigilance.
860- Consider using an immutable helper library such as
861- <a href="https://facebook.github.io/immutable-js/" target="_blank" title="Immutable">Immutable.js</a>.
822+ Had you assigned the `formModel.secretLairs` to `saveHero.addresses` (see line commented out),
823+ the addresses in `saveHero.addresses` array would be the same objects
824+ as the lairs in the `formModel.secretLairs`.
825+ A user's subsequent changes to a lair street would mutate an address street in the `saveHero`.
826+
827+ The `prepareSaveHero` method makes copies of the form model's `secretLairs` objects so that can't happen.
862828
863829:marked
864830 ### Revert (cancel changes)
865831 The user cancels changes and reverts the form to the original state by pressing the _Revert_ button.
866832
867- Reverting is easy. Simply re-execute the `ngOnChanges` method that built the _form model_ from the current `hero` _data model_.
868- The immutability rule guarantees that the `hero` hasn't changed.
833+ Reverting is easy. Simply re-execute the `ngOnChanges` method that built the _form model_ from the original, unchanged `hero` _data model_.
869834+ makeExample('reactive-forms/ts/app/hero-detail.component.ts' , 'revert' ,'app/hero-detail.component.ts (revert)' )( format ="." )
870835
871836:marked
@@ -894,7 +859,7 @@ figure.image-display
894859 - Inspecting `FormControl` properties.
895860 - Setting data with `patchValue` and `setValue`.
896861 - Adding groups dynamically with `FormArray`.
897- - Watching for changes to the value of a `FormControl`.
862+ - Observing changes to the value of a `FormControl`.
898863 - Saving form changes.
899864
900865a#source-code
0 commit comments