| 
									
										
										
										
											2017-05-26 21:28:06 +02:00
										 |  |  | # Component Interaction
 | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | {@a top} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This cookbook contains recipes for common component communication scenarios | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | in which two or more components share information. | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | {@a toc} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-04 18:46:43 +02:00
										 |  |  | <!--
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | # Contents
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-08 20:47:34 -07:00
										 |  |  | * [Pass data from parent to child with input binding](guide/component-interaction#parent-to-child) | 
					
						
							|  |  |  | * [Intercept input property changes with a setter](guide/component-interaction#parent-to-child-setter) | 
					
						
							|  |  |  | * [Intercept input property changes with `ngOnChanges()`](guide/component-interaction#parent-to-child-on-changes) | 
					
						
							|  |  |  | * [Parent calls an `@ViewChild()`](guide/component-interaction#parent-to-view-child) | 
					
						
							|  |  |  | * [Parent and children communicate via a service](guide/component-interaction#bidirectional-service) | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-04 18:46:43 +02:00
										 |  |  | --> | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-08 20:47:34 -07:00
										 |  |  | **See the <live-example name="component-interaction"></live-example>**. | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | {@a parent-to-child} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Pass data from parent to child with input binding
 | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | `HeroChildComponent` has two ***input properties***, | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | typically adorned with [@Input decorations](guide/template-syntax#inputs-outputs). | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-08 20:47:34 -07:00
										 |  |  | <code-example path="component-interaction/src/app/hero-child.component.ts" title="component-interaction/src/app/hero-child.component.ts"> | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | </code-example> | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | The second `@Input` aliases the child component property name `masterName` as `'master'`. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | The `HeroParentComponent` nests the child `HeroChildComponent` inside an `*ngFor` repeater, | 
					
						
							|  |  |  | binding its `master` string property to the child's `master` alias, | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | and each iteration's `hero` instance to the child's `hero` property. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-08 20:47:34 -07:00
										 |  |  | <code-example path="component-interaction/src/app/hero-parent.component.ts" title="component-interaction/src/app/hero-parent.component.ts"> | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | </code-example> | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | The running application displays three heroes: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-30 20:04:18 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-09 23:53:32 +01:00
										 |  |  | <figure> | 
					
						
							|  |  |  |   <img src="generated/images/guide/component-interaction/parent-to-child.png" alt="Parent-to-child"> | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | </figure> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-08 20:47:34 -07:00
										 |  |  | <h3 class="no-toc">Test it</h3> | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | E2E test that all children were instantiated and displayed as expected: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-08 20:47:34 -07:00
										 |  |  | <code-example path="component-interaction/e2e-spec.ts" region="parent-to-child" title="component-interaction/e2e-spec.ts"> | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | </code-example> | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-08 20:47:34 -07:00
										 |  |  | [Back to top](guide/component-interaction#top) | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | {@a parent-to-child-setter} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Intercept input property changes with a setter
 | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | Use an input property setter to intercept and act upon a value from the parent. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | The setter of the `name` input property in the child `NameChildComponent` | 
					
						
							|  |  |  | trims the whitespace from a name and replaces an empty value with default text. | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-08 20:47:34 -07:00
										 |  |  | <code-example path="component-interaction/src/app/name-child.component.ts" title="component-interaction/src/app/name-child.component.ts"> | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | </code-example> | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | Here's the `NameParentComponent` demonstrating name variations including a name with all spaces: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-08 20:47:34 -07:00
										 |  |  | <code-example path="component-interaction/src/app/name-parent.component.ts" title="component-interaction/src/app/name-parent.component.ts"> | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | </code-example> | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-30 20:04:18 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-09 23:53:32 +01:00
										 |  |  | <figure> | 
					
						
							|  |  |  |   <img src="generated/images/guide/component-interaction/setter.png" alt="Parent-to-child-setter"> | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | </figure> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-08 20:47:34 -07:00
										 |  |  | <h3 class="no-toc">Test it</h3> | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | E2E tests of input property setter with empty and non-empty names: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-08 20:47:34 -07:00
										 |  |  | <code-example path="component-interaction/e2e-spec.ts" region="parent-to-child-setter" title="component-interaction/e2e-spec.ts"> | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | </code-example> | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-08 20:47:34 -07:00
										 |  |  | [Back to top](guide/component-interaction#top) | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | {@a parent-to-child-on-changes} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Intercept input property changes with *ngOnChanges()*
 | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | Detect and act upon changes to input property values with the `ngOnChanges()` method of the `OnChanges` lifecycle hook interface. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-10 16:51:13 +01:00
										 |  |  | <div class="l-sub-section"> | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | You may prefer this approach to the property setter when watching multiple, interacting input properties. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Learn about `ngOnChanges()` in the [LifeCycle Hooks](guide/lifecycle-hooks) chapter. | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-10 16:51:13 +01:00
										 |  |  | </div> | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | This `VersionChildComponent` detects changes to the `major` and `minor` input properties and composes a log message reporting these changes: | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-08 20:47:34 -07:00
										 |  |  | <code-example path="component-interaction/src/app/version-child.component.ts" title="component-interaction/src/app/version-child.component.ts"> | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | </code-example> | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | The `VersionParentComponent` supplies the `minor` and `major` values and binds buttons to methods that change them. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-08 20:47:34 -07:00
										 |  |  | <code-example path="component-interaction/src/app/version-parent.component.ts" title="component-interaction/src/app/version-parent.component.ts"> | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | </code-example> | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | Here's the output of a button-pushing sequence: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-30 20:04:18 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-09 23:53:32 +01:00
										 |  |  | <figure> | 
					
						
							|  |  |  |   <img src="generated/images/guide/component-interaction/parent-to-child-on-changes.gif" alt="Parent-to-child-onchanges"> | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | </figure> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-08 20:47:34 -07:00
										 |  |  | <h3 class="no-toc">Test it</h3> | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | Test that ***both*** input properties are set initially and that button clicks trigger | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | the expected `ngOnChanges` calls and values: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-08 20:47:34 -07:00
										 |  |  | <code-example path="component-interaction/e2e-spec.ts" region="parent-to-child-onchanges" title="component-interaction/e2e-spec.ts"> | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | </code-example> | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-08 20:47:34 -07:00
										 |  |  | [Back to top](guide/component-interaction#top) | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | {@a child-to-parent} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Parent listens for child event
 | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | The child component exposes an `EventEmitter` property with which it `emits` events when something happens. | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | The parent binds to that event property and reacts to those events. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | The child's `EventEmitter` property is an ***output property***, | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  |   typically adorned with an [@Output decoration](guide/template-syntax#inputs-outputs) | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  |   as seen in this `VoterComponent`: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-08 20:47:34 -07:00
										 |  |  | <code-example path="component-interaction/src/app/voter.component.ts" title="component-interaction/src/app/voter.component.ts"> | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | </code-example> | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | Clicking a button triggers emission of a `true` or `false`, the boolean *payload*. | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | The parent `VoteTakerComponent` binds an event handler called `onVoted()` that responds to the child event | 
					
						
							|  |  |  | payload `$event` and updates a counter. | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-08 20:47:34 -07:00
										 |  |  | <code-example path="component-interaction/src/app/votetaker.component.ts" title="component-interaction/src/app/votetaker.component.ts"> | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | </code-example> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | The framework passes the event argument—represented by `$event`—to the handler method, | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | and the method processes it: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-30 20:04:18 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-09 23:53:32 +01:00
										 |  |  | <figure> | 
					
						
							|  |  |  |   <img src="generated/images/guide/component-interaction/child-to-parent.gif" alt="Child-to-parent"> | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | </figure> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-08 20:47:34 -07:00
										 |  |  | <h3 class="no-toc">Test it</h3> | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | Test that clicking the *Agree* and *Disagree* buttons update the appropriate counters: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-08 20:47:34 -07:00
										 |  |  | <code-example path="component-interaction/e2e-spec.ts" region="child-to-parent" title="component-interaction/e2e-spec.ts"> | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | </code-example> | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-08 20:47:34 -07:00
										 |  |  | [Back to top](guide/component-interaction#top) | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | ## Parent interacts with child via *local variable*
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | A parent component cannot use data binding to read child properties | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | or invoke child methods. You can do both | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | by creating a template reference variable for the child element | 
					
						
							|  |  |  | and then reference that variable *within the parent template* | 
					
						
							|  |  |  | as seen in the following example. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | {@a countdown-timer-example} | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | The following is a child `CountdownTimerComponent` that repeatedly counts down to zero and launches a rocket. | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | It has `start` and `stop` methods that control the clock and it displays a | 
					
						
							|  |  |  | countdown status message in its own template. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-08 20:47:34 -07:00
										 |  |  | <code-example path="component-interaction/src/app/countdown-timer.component.ts" title="component-interaction/src/app/countdown-timer.component.ts"> | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | </code-example> | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | The `CountdownLocalVarParentComponent` that hosts the timer component is as follows: | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-08 20:47:34 -07:00
										 |  |  | <code-example path="component-interaction/src/app/countdown-parent.component.ts" region="lv" title="component-interaction/src/app/countdown-parent.component.ts"> | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | </code-example> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | The parent component cannot data bind to the child's | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | `start` and `stop` methods nor to its `seconds` property. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | You can place a local variable, `#timer`, on the tag `<countdown-timer>` representing the child component. | 
					
						
							|  |  |  | That gives you a reference to the child component and the ability to access | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | *any of its properties or methods* from within the parent template. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | This example wires parent buttons to the child's `start` and `stop` and | 
					
						
							|  |  |  | uses interpolation to display the child's `seconds` property. | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | Here we see the parent and child working together. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-30 20:04:18 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-09 23:53:32 +01:00
										 |  |  | <figure> | 
					
						
							|  |  |  |   <img src="generated/images/guide/component-interaction/countdown-timer-anim.gif" alt="countdown timer"> | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | </figure> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | {@a countdown-tests} | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-08 20:47:34 -07:00
										 |  |  | <h3 class="no-toc">Test it</h3> | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | Test that the seconds displayed in the parent template | 
					
						
							|  |  |  | match the seconds displayed in the child's status message. | 
					
						
							|  |  |  | Test also that clicking the *Stop* button pauses the countdown timer: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-08 20:47:34 -07:00
										 |  |  | <code-example path="component-interaction/e2e-spec.ts" region="countdown-timer-tests" title="component-interaction/e2e-spec.ts"> | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | </code-example> | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-08 20:47:34 -07:00
										 |  |  | [Back to top](guide/component-interaction#top) | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | {@a parent-to-view-child} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Parent calls an _@ViewChild()_
 | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | The *local variable* approach is simple and easy. But it is limited because | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | the parent-child wiring must be done entirely within the parent template. | 
					
						
							|  |  |  | The parent component *itself* has no access to the child. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | You can't use the *local variable* technique if an instance of the parent component *class* | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | must read or write child component values or must call child component methods. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | When the parent component *class* requires that kind of access, | 
					
						
							|  |  |  | ***inject*** the child component into the parent as a *ViewChild*. | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-26 15:11:02 +03:00
										 |  |  | The following example illustrates this technique with the same | 
					
						
							| 
									
										
										
										
											2017-05-08 20:47:34 -07:00
										 |  |  | [Countdown Timer](guide/component-interaction#countdown-timer-example) example. | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | Neither its appearance nor its behavior will change. | 
					
						
							| 
									
										
										
										
											2017-05-08 20:47:34 -07:00
										 |  |  | The child [CountdownTimerComponent](guide/component-interaction#countdown-timer-example) is the same as well. | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-10 16:51:13 +01:00
										 |  |  | <div class="l-sub-section"> | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | The switch from the *local variable* to the *ViewChild* technique | 
					
						
							|  |  |  | is solely for the purpose of demonstration. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-10 16:51:13 +01:00
										 |  |  | </div> | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | Here is the parent, `CountdownViewChildParentComponent`: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-08 20:47:34 -07:00
										 |  |  | <code-example path="component-interaction/src/app/countdown-parent.component.ts" region="vc" title="component-interaction/src/app/countdown-parent.component.ts"> | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | </code-example> | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | It takes a bit more work to get the child view into the parent component *class*. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | First, you have to import references to the `ViewChild` decorator and the `AfterViewInit` lifecycle hook. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Next, inject the child `CountdownTimerComponent` into the private `timerComponent` property | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | via the `@ViewChild` property decoration. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | The `#timer` local variable is gone from the component metadata. | 
					
						
							|  |  |  | Instead, bind the buttons to the parent component's own `start` and `stop` methods and | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | present the ticking seconds in an interpolation around the parent component's `seconds` method. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | These methods access the injected timer component directly. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | The `ngAfterViewInit()` lifecycle hook is an important wrinkle. | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | The timer component isn't available until *after* Angular displays the parent view. | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | So it displays `0` seconds initially. | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | Then Angular calls the `ngAfterViewInit` lifecycle hook at which time it is *too late* | 
					
						
							|  |  |  | to update the parent view's display of the countdown seconds. | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | Angular's unidirectional data flow rule prevents updating the parent view's | 
					
						
							|  |  |  | in the same cycle. The app has to *wait one turn* before it can display the seconds. | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | Use `setTimeout()` to wait one tick and then revise the `seconds()` method so | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | that it takes future values from the timer component. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-08 20:47:34 -07:00
										 |  |  | <h3 class="no-toc">Test it</h3> | 
					
						
							|  |  |  | Use [the same countdown timer tests](guide/component-interaction#countdown-tests) as before. | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-08 20:47:34 -07:00
										 |  |  | [Back to top](guide/component-interaction#top) | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | {@a bidirectional-service} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Parent and children communicate via a service
 | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | A parent component and its children share a service whose interface enables bi-directional communication | 
					
						
							|  |  |  | *within the family*. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | The scope of the service instance is the parent component and its children. | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | Components outside this component subtree have no access to the service or their communications. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This `MissionService` connects the `MissionControlComponent` to multiple `AstronautComponent` children. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-08 20:47:34 -07:00
										 |  |  | <code-example path="component-interaction/src/app/mission.service.ts" title="component-interaction/src/app/mission.service.ts"> | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | </code-example> | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | The `MissionControlComponent` both provides the instance of the service that it shares with its children | 
					
						
							|  |  |  | (through the `providers` metadata array) and injects that instance into itself through its constructor: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-08 20:47:34 -07:00
										 |  |  | <code-example path="component-interaction/src/app/missioncontrol.component.ts" title="component-interaction/src/app/missioncontrol.component.ts"> | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | </code-example> | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | The `AstronautComponent` also injects the service in its constructor. | 
					
						
							|  |  |  | Each `AstronautComponent` is a child of the `MissionControlComponent` and therefore receives its parent's service instance: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-08 20:47:34 -07:00
										 |  |  | <code-example path="component-interaction/src/app/astronaut.component.ts" title="component-interaction/src/app/astronaut.component.ts"> | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | </code-example> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-10 16:51:13 +01:00
										 |  |  | <div class="l-sub-section"> | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | Notice that this example captures the `subscription` and `unsubscribe()` when the `AstronautComponent` is destroyed. | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | This is a memory-leak guard step. There is no actual risk in this app because the | 
					
						
							|  |  |  | lifetime of a `AstronautComponent` is the same as the lifetime of the app itself. | 
					
						
							|  |  |  | That *would not* always be true in a more complex application. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | You don't add this guard to the `MissionControlComponent` because, as the parent, | 
					
						
							|  |  |  | it controls the lifetime of the `MissionService`. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-10 16:51:13 +01:00
										 |  |  | </div> | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | The *History* log demonstrates that messages travel in both directions between | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | the parent `MissionControlComponent` and the `AstronautComponent` children, | 
					
						
							|  |  |  | facilitated by the service: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-30 20:04:18 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-09 23:53:32 +01:00
										 |  |  | <figure> | 
					
						
							|  |  |  |   <img src="generated/images/guide/component-interaction/bidirectional-service.gif" alt="bidirectional-service"> | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | </figure> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-08 20:47:34 -07:00
										 |  |  | <h3 class="no-toc">Test it</h3> | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | Tests click buttons of both the parent `MissionControlComponent` and the `AstronautComponent` children | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | and verify that the history meets expectations: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-08 20:47:34 -07:00
										 |  |  | <code-example path="component-interaction/e2e-spec.ts" region="bidirectional-service" title="component-interaction/e2e-spec.ts"> | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-27 16:08:53 +01:00
										 |  |  | </code-example> | 
					
						
							| 
									
										
										
										
											2017-02-22 18:09:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-04-01 01:57:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-08 20:47:34 -07:00
										 |  |  | [Back to top](guide/component-interaction#top) |