Skip to content

Commit

Permalink
docs(docs-infra): clarify toh-2 error message (#45878)
Browse files Browse the repository at this point in the history
the second step of the tour of heroes refers to a runtime error which
generally isn't presented to new users since it gets caught by the
TypeScript compiler's strict mode, clarify such detail so not to confuse
readers

resolves #45759

PR Close #45878
  • Loading branch information
dario-piotrowicz authored and AndrewKushnir committed May 9, 2022
1 parent eae93b2 commit 4d27448
Show file tree
Hide file tree
Showing 2 changed files with 5 additions and 46 deletions.
Expand Up @@ -11,17 +11,13 @@ <h2>My Heroes</h2>
<!-- #enddocregion li -->
</ul>

<!-- #docregion ng-if -->
<!-- #docregion selectedHero-details -->
<div *ngIf="selectedHero">

<!-- #docregion selectedHero-details -->
<h2>{{selectedHero.name | uppercase}} Details</h2>
<div>id: {{selectedHero.id}}</div>
<div>
<label for="hero-name">Hero name: </label>
<input id="hero-name" [(ngModel)]="selectedHero.name" placeholder="name">
</div>
<!-- #enddocregion selectedHero-details -->

</div>
<!-- #enddocregion ng-if -->
<!-- #enddocregion selectedHero-details -->
43 changes: 3 additions & 40 deletions aio/content/tutorial/toh-pt2.md
Expand Up @@ -117,7 +117,7 @@ The `heroes.component.css` styles apply only to the `HeroesComponent` and don't

When the user clicks a hero in the list, the component should display the selected hero's details at the bottom of the page.

In this section, you'll listen for the hero item click event and update the hero detail.
In this section, you'll listen for the hero item click event and display/update the hero details.

### Add a click event binding

Expand All @@ -134,8 +134,7 @@ In the next section, define an `onSelect()` method in `HeroesComponent` to displ

### Add the click event handler

Rename the component's `hero` property to `selectedHero` but don't assign it.
There is no *selected hero* when the application starts.
Rename the component's `hero` property to `selectedHero` but don't assign any value to it since there is no *selected hero* when the application starts.

Add the following `onSelect()` method, which assigns the clicked hero from the template to the component's `selectedHero`.

Expand All @@ -149,28 +148,7 @@ Add the following to `heroes.component.html` beneath the list section:

<code-example header="heroes.component.html (selected hero details)" path="toh-pt2/src/app/heroes/heroes.component.html" region="selectedHero-details"></code-example>

After the browser refreshes, the application is broken.

Open the browser developer tools and look in the console for an error message like this:

<code-example format="output" hideCopy language="shell">

HeroesComponent.html:3 ERROR TypeError: Cannot read property 'name' of undefined

</code-example>

#### What happened?

When the application starts, the `selectedHero` is `undefined` *by design*.

Binding expressions in the template that refer to properties of `selectedHero` &mdash;expressions like `{{selectedHero.name}}`&mdash; *must fail* because there is no selected hero.

#### The fix - hide empty details with `*ngIf`

The component should only display the selected hero details if the `selectedHero` exists.

Wrap the hero detail HTML in a `<div>`.
Add Angular's `*ngIf` directive to the `<div>` and set it to `selectedHero`.
The hero details should only be displayed when a hero is selected. When a component is created initially, there is no selected hero, so we add the `*ngIf` directive to the `<div>` that wraps the hero details, to instruct Angular to render the section only when the `selectedHero` is actually defined (after it has been selected by clicking on a hero).

<div class="alert is-important">

Expand All @@ -179,21 +157,6 @@ It's a critical part of the syntax.

</div>

<code-example header="src/app/heroes/heroes.component.html (*ngIf)" path="toh-pt2/src/app/heroes/heroes.component.html" region="ng-if"></code-example>

After the browser refreshes, the list of names reappears.
The details area is blank.
Click a hero in the list of heroes and its details appear.
The application seems to be working again.
The heroes appear in a list and details about the clicked hero appear at the bottom of the page.

#### Why it works

When `selectedHero` is undefined, the `ngIf` removes the hero detail from the DOM.
There are no `selectedHero` bindings to consider.

When the user picks a hero, `selectedHero` has a value and `ngIf` puts the hero detail into the DOM.

### Style the selected hero

To help identify the selected hero, you can use the `.selected` CSS class in the [styles you added earlier](#styles).
Expand Down

0 comments on commit 4d27448

Please sign in to comment.