feat(docs-infra): implement figure styles (#33259)

PR#28396 originally addressed an update via issue #23983 to make images more visible with a white background (implementation of gray "lightbox").

This PR implements those styles defined in PR#28396.

PR Close #33259
This commit is contained in:
Stefanie Fluin 2019-10-18 16:22:06 -07:00 committed by Andrew Kushnir
parent 355e54a410
commit ba29e4d953
46 changed files with 666 additions and 340 deletions

View File

@ -69,8 +69,10 @@ Let's animate a simple transition that changes a single HTML element from one st
In HTML, these attributes are set using ordinary CSS styles such as color and opacity. In Angular, use the `style()` function to specify a set of CSS styles for use with animations. You can collect a set of styles in an animation state, and give the state a name, such as `open` or `closed`.
<figure>
<img src="generated/images/guide/animations/open-closed.png" alt="open and closed states">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/animations/open-closed.png" alt="open and closed states">
</div>
</figure>
### Animation state and styles
@ -166,8 +168,10 @@ The `trigger()` function describes the property name to watch for changes. When
In this example, we'll name the trigger `openClose`, and attach it to the `button` element. The trigger describes the open and closed states, and the timings for the two transitions.
<figure>
<img src="generated/images/guide/animations/triggering-the-animation.png" alt="triggering the animation">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/animations/triggering-the-animation.png" alt="triggering the animation">
</div>
</figure>
<div class="alert is-helpful">

View File

@ -51,8 +51,10 @@ You define a component's view with its companion template. A template is a form
Views are typically arranged hierarchically, allowing you to modify or show and hide entire UI sections or pages as a unit. The template immediately associated with a component defines that component's *host view*. The component can also define a *view hierarchy*, which contains *embedded views*, hosted by other components.
<figure>
<img src="generated/images/guide/architecture/component-tree.png" alt="Component tree" class="left">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/architecture/component-tree.png" alt="Component tree" class="left">
</div>
</figure>
A view hierarchy can include views from components in the same NgModule, but it also can (and often does) include views from components that are defined in different NgModules.
@ -81,8 +83,10 @@ Angular supports *two-way data binding*, a mechanism for coordinating the parts
The following diagram shows the four forms of data binding markup. Each form has a direction: to the DOM, from the DOM, or both.
<figure>
<img src="generated/images/guide/architecture/databinding.png" alt="Data Binding" class="left">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/architecture/databinding.png" alt="Data Binding" class="left">
</div>
</figure>
This example from the `HeroListComponent` template uses three of these forms.
@ -110,14 +114,18 @@ as with event binding.
Angular processes *all* data bindings once for each JavaScript event cycle,
from the root of the application component tree through all child components.
<figure>
<img src="generated/images/guide/architecture/component-databinding.png" alt="Data Binding" class="left">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/architecture/component-databinding.png" alt="Data Binding" class="left">
</div>
</figure>
Data binding plays an important role in communication between a template and its component, and is also important for communication between parent and child components.
<figure>
<img src="generated/images/guide/architecture/parent-child-binding.png" alt="Parent/Child binding" class="left">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/architecture/parent-child-binding.png" alt="Parent/Child binding" class="left">
</div>
</figure>
### Pipes

View File

@ -35,20 +35,20 @@ Here's a simple root NgModule definition.
NgModules provide a *compilation context* for their components. A root NgModule always has a root component that is created during bootstrap, but any NgModule can include any number of additional components, which can be loaded through the router or created through the template. The components that belong to an NgModule share a compilation context.
<figure>
<img src="generated/images/guide/architecture/compilation-context.png" alt="Component compilation context" class="left">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/architecture/compilation-context.png" alt="Component compilation context" class="left">
</div>
</figure>
<br class="clear">
A component and its template together define a *view*. A component can contain a *view hierarchy*, which allows you to define arbitrarily complex areas of the screen that can be created, modified, and destroyed as a unit. A view hierarchy can mix views defined in components that belong to different NgModules. This is often the case, especially for UI libraries.
<figure>
<img src="generated/images/guide/architecture/view-hierarchy.png" alt="View hierarchy" class="left">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/architecture/view-hierarchy.png" alt="View hierarchy" class="left">
</div>
</figure>
<br class="clear">

View File

@ -70,8 +70,10 @@ When all requested services have been resolved and returned, Angular can call th
The process of `HeroService` injection looks something like this.
<figure>
<img src="generated/images/guide/architecture/injector-injects.png" alt="Service" class="left">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/architecture/injector-injects.png" alt="Service" class="left">
</div>
</figure>
### Providing services

View File

@ -113,8 +113,10 @@ To define navigation rules, you associate *navigation paths* with your component
You've learned the basics about the main building blocks of an Angular application. The following diagram shows how these basic pieces are related.
<figure>
<img src="generated/images/guide/architecture/overview2.png" alt="overview">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/architecture/overview2.png" alt="overview">
</div>
</figure>
* Together, a component and template define an Angular view.

View File

@ -175,8 +175,10 @@ Here's the updated directive in full:
Run the app and confirm that the background color appears when
the mouse hovers over the `p` and disappears as it moves out.
<figure>
<img src="generated/images/guide/attribute-directives/highlight-directive-anim.gif" alt="Second Highlight">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/attribute-directives/highlight-directive-anim.gif" alt="Second Highlight">
</div>
</figure>
{@a bindings}
@ -271,8 +273,10 @@ Revise the `AppComponent.color` so that it has no initial value.
Here are the harness and directive in action.
<figure>
<img src="generated/images/guide/attribute-directives/highlight-directive-v2-anim.gif" alt="Highlight v.2">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/attribute-directives/highlight-directive-v2-anim.gif" alt="Highlight v.2">
</div>
</figure>
{@a second-property}
@ -307,8 +311,10 @@ because you made it _public_ with the `@Input` decorator.
Here's how the harness should work when you're done coding.
<figure>
<img src="generated/images/guide/attribute-directives/highlight-directive-final-anim.gif" alt="Final Highlight">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/attribute-directives/highlight-directive-final-anim.gif" alt="Final Highlight">
</div>
</figure>
## Summary

View File

@ -50,8 +50,10 @@ and each iteration's `hero` instance to the child's `hero` property.
The running application displays three heroes:
<figure>
<img src="generated/images/guide/component-interaction/parent-to-child.png" alt="Parent-to-child">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/component-interaction/parent-to-child.png" alt="Parent-to-child">
</div>
</figure>
@ -94,8 +96,10 @@ Here's the `NameParentComponent` demonstrating name variations including a name
<figure>
<img src="generated/images/guide/component-interaction/setter.png" alt="Parent-to-child-setter">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/component-interaction/setter.png" alt="Parent-to-child-setter">
</div>
</figure>
@ -152,8 +156,10 @@ The `VersionParentComponent` supplies the `minor` and `major` values and binds b
Here's the output of a button-pushing sequence:
<figure>
<img src="generated/images/guide/component-interaction/parent-to-child-on-changes.gif" alt="Parent-to-child-onchanges">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/component-interaction/parent-to-child-on-changes.gif" alt="Parent-to-child-onchanges">
</div>
</figure>
@ -206,8 +212,10 @@ The framework passes the event argument&mdash;represented by `$event`&mdash;to t
and the method processes it:
<figure>
<img src="generated/images/guide/component-interaction/child-to-parent.gif" alt="Child-to-parent">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/component-interaction/child-to-parent.gif" alt="Child-to-parent">
</div>
</figure>
@ -268,8 +276,10 @@ uses interpolation to display the child's `seconds` property.
Here we see the parent and child working together.
<figure>
<img src="generated/images/guide/component-interaction/countdown-timer-anim.gif" alt="countdown timer">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/component-interaction/countdown-timer-anim.gif" alt="countdown timer">
</div>
</figure>
@ -421,8 +431,10 @@ the parent `MissionControlComponent` and the `AstronautComponent` children,
facilitated by the service:
<figure>
<img src="generated/images/guide/component-interaction/bidirectional-service.gif" alt="bidirectional-service">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/component-interaction/bidirectional-service.gif" alt="bidirectional-service">
</div>
</figure>

View File

@ -40,8 +40,10 @@ and the framework resolves the nested dependencies.
When all dependencies are in place, `AppComponent` displays the user information.
<figure>
<img src="generated/images/guide/dependency-injection-in-action/logged-in-user.png" alt="Logged In User">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/dependency-injection-in-action/logged-in-user.png" alt="Logged In User">
</div>
</figure>
{@a service-scope}
@ -131,8 +133,10 @@ The template displays this data-bound property.
Find this example in <live-example name="dependency-injection-in-action">live code</live-example>
and confirm that the three `HeroBioComponent` instances have their own cached hero data.
<figure>
<img src="generated/images/guide/dependency-injection-in-action/hero-bios.png" alt="Bios">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/dependency-injection-in-action/hero-bios.png" alt="Bios">
</div>
</figure>
{@a qualify-dependency-lookup}
@ -191,8 +195,10 @@ placing it in the `<ng-content>` slot of the `HeroBioComponent` template.
The result is shown below, with the hero's telephone number from `HeroContactComponent` projected above the hero description.
<figure>
<img src="generated/images/guide/dependency-injection-in-action/hero-bio-and-content.png" alt="bio and contact">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/dependency-injection-in-action/hero-bio-and-content.png" alt="bio and contact">
</div>
</figure>
@ -221,8 +227,10 @@ When the property is marked as optional, Angular sets `loggerService` to null an
Here's `HeroBiosAndContactsComponent` in action.
<figure>
<img src="generated/images/guide/dependency-injection-in-action/hero-bios-and-contacts.png" alt="Bios with contact into">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/dependency-injection-in-action/hero-bios-and-contacts.png" alt="Bios with contact into">
</div>
</figure>
@ -232,8 +240,10 @@ until it finds the logger at the `AppComponent` level.
The logger logic kicks in and the hero display updates
with the "!!!" marker to indicate that the logger was found.
<figure>
<img src="generated/images/guide/dependency-injection-in-action/hero-bio-contact-no-host.png" alt="Without @Host">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/dependency-injection-in-action/hero-bio-contact-no-host.png" alt="Without @Host">
</div>
</figure>
@ -294,8 +304,10 @@ first without a value (yielding the default color) and then with an assigned col
The following image shows the effect of mousing over the `<hero-bios-and-contacts>` tag.
<figure>
<img src="generated/images/guide/dependency-injection-in-action/highlight.png" alt="Highlighted bios">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/dependency-injection-in-action/highlight.png" alt="Highlighted bios">
</div>
</figure>
{@a providers}
@ -347,8 +359,10 @@ You learned about some other methods in [Dependency Providers](guide/dependency-
The following `HeroOfTheMonthComponent` example demonstrates many of the alternatives and why you need them.
It's visually simple: a few properties and the logs produced by a logger.
<figure>
<img src="generated/images/guide/dependency-injection-in-action/hero-of-month.png" alt="Hero of the month">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/dependency-injection-in-action/hero-of-month.png" alt="Hero of the month">
</div>
</figure>
The code behind it customizes how and where the DI framework provides dependencies.
@ -460,8 +474,10 @@ The following example puts `MinimalLogger` to use in a simplified version of `He
The `HeroOfTheMonthComponent` constructor's `logger` parameter is typed as `MinimalLogger`, so only the `logs` and `logInfo` members are visible in a TypeScript-aware editor.
<figure>
<img src="generated/images/guide/dependency-injection-in-action/minimal-logger-intellisense.png" alt="MinimalLogger restricted API">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/dependency-injection-in-action/minimal-logger-intellisense.png" alt="MinimalLogger restricted API">
</div>
</figure>
@ -472,8 +488,10 @@ Behind the scenes, Angular sets the `logger` parameter to the full service regis
This is illustrated in the following image, which displays the logging date.
<figure>
<img src="generated/images/guide/dependency-injection-in-action/date-logger-entry.png" alt="DateLoggerService entry">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/dependency-injection-in-action/date-logger-entry.png" alt="DateLoggerService entry">
</div>
</figure>
</div>
@ -627,8 +645,10 @@ and then pass them down to the base class through the constructor.
In this contrived example, `SortedHeroesComponent` inherits from `HeroesBaseComponent`
to display a *sorted* list of heroes.
<figure>
<img src="generated/images/guide/dependency-injection-in-action/sorted-heroes.png" alt="Sorted Heroes">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/dependency-injection-in-action/sorted-heroes.png" alt="Sorted Heroes">
</div>
</figure>
The `HeroesBaseComponent` can stand on its own.

View File

@ -145,8 +145,10 @@ the same way you've done it before.
Here's *Alex* and family in action.
<figure>
<img src="generated/images/guide/dependency-injection-in-action/alex.png" alt="Alex in action">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/dependency-injection-in-action/alex.png" alt="Alex in action">
</div>
</figure>
@ -201,8 +203,10 @@ which *is* what parent means.
Here's *Alice*, *Barry*, and family in action.
<figure>
<img src="generated/images/guide/dependency-injection-in-action/alice.png" alt="Alice in action">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/dependency-injection-in-action/alice.png" alt="Alice in action">
</div>
</figure>

View File

@ -386,8 +386,10 @@ showing exactly which classes are included in the bundle.
Here's the output for the _main_ bundle of an example app called `cli-quickstart`.
<figure>
<img src="generated/images/guide/deployment/quickstart-sourcemap-explorer.png" alt="quickstart sourcemap explorer">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/deployment/quickstart-sourcemap-explorer.png" alt="quickstart sourcemap explorer">
</div>
</figure>
{@a base-tag}

View File

@ -9,8 +9,10 @@ conditionally show a message below the list.
The final UI looks like this:
<figure>
<img src="generated/images/guide/displaying-data/final.png" alt="Final UI">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/displaying-data/final.png" alt="Final UI">
</div>
</figure>
<div class="alert is-helpful">
@ -103,8 +105,10 @@ inside the `<app-root>` tag.
Now run the app. It should display the title and hero name:
<figure>
<img src="generated/images/guide/displaying-data/title-and-hero.png" alt="Title and Hero">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/displaying-data/title-and-hero.png" alt="Title and Hero">
</div>
</figure>
@ -212,8 +216,10 @@ repeat items for any [iterable](https://developer.mozilla.org/en-US/docs/Web/Jav
Now the heroes appear in an unordered list.
<figure>
<img src="generated/images/guide/displaying-data/hero-names-list.png" alt="After ngfor">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/displaying-data/hero-names-list.png" alt="After ngfor">
</div>
</figure>

View File

@ -183,8 +183,10 @@ Here are two sample components and the `AdComponent` interface for reference:
## Final ad banner
The final ad banner looks like this:
<figure>
<img src="generated/images/guide/dynamic-component-loader/ads-example.gif" alt="Ads">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/dynamic-component-loader/ads-example.gif" alt="Ads">
</div>
</figure>

View File

@ -197,8 +197,10 @@ Saving and retrieving the data is an exercise for another time.
The final form looks like this:
<figure>
<img src="generated/images/guide/dynamic-form/dynamic-form.png" alt="Dynamic-Form">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/dynamic-form/dynamic-form.png" alt="Dynamic-Form">
</div>
</figure>

View File

@ -42,10 +42,10 @@ After you register your configured class with the browser's custom-element regis
When your custom element is placed on a page, the browser creates an instance of the registered class and adds it to the DOM. The content is provided by the component's template, which uses Angular template syntax, and is rendered using the component and DOM data. Input properties in the component correspond to input attributes for the element.
<figure>
<img src="generated/images/guide/elements/customElement1.png" alt="Custom element in browser" class="left">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/elements/customElement1.png" alt="Custom element in browser" class="left">
</div>
</figure>
<hr class="clear">
@ -64,10 +64,10 @@ Use a JavaScript function, `customElements.define()`, to register the configure
and its associated custom-element tag with the browser's `CustomElementRegistry`.
When the browser encounters the tag for the registered element, it uses the constructor to create a custom-element instance.
<figure>
<img src="generated/images/guide/elements/createElement.png" alt="Transform a component to a custom element" class="left">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/elements/createElement.png" alt="Transform a component to a custom element" class="left">
</div>
</figure>
### Mapping

View File

@ -103,8 +103,10 @@ Next, in the `AppComponent`, `app.component.html`, add the tag `<app-customer-da
Now, in addition to the title that renders by default, the `CustomerDashboardComponent` template renders too:
<figure>
<img src="generated/images/guide/feature-modules/feature-module.png" alt="feature module component">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/feature-modules/feature-module.png" alt="feature module component">
</div>
</figure>
<hr />

View File

@ -67,8 +67,10 @@ Here's a component with an input field for a single control implemented using re
The source of truth provides the value and status of the form element at a given point in time. In reactive forms, the form model is the source of truth. In the example above, the form model is the `FormControl` instance.
<figure>
<img src="generated/images/guide/forms-overview/key-diff-reactive-forms.png" alt="Reactive forms key differences">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/forms-overview/key-diff-reactive-forms.png" alt="Reactive forms key differences">
</div>
</figure>
With reactive forms, the form model is explicitly defined in the component class. The reactive form directive (in this case, `FormControlDirective`) then links the existing `FormControl` instance to a specific form element in the view using a value accessor (`ControlValueAccessor` instance).
@ -82,8 +84,10 @@ Here's the same component with an input field for a single control implemented u
In template-driven forms, the source of truth is the template.
<figure>
<img src="generated/images/guide/forms-overview/key-diff-td-forms.png" alt="Template-driven forms key differences">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/forms-overview/key-diff-td-forms.png" alt="Template-driven forms key differences">
</div>
</figure>
The abstraction of the form model promotes simplicity over structure. The template-driven form directive `NgModel` is responsible for creating and managing the `FormControl` instance for a given form element. It's less explicit, but you no longer have direct control over the form model.
@ -98,8 +102,10 @@ When building forms in Angular, it's important to understand how the framework h
As described above, in reactive forms each form element in the view is directly linked to a form model (`FormControl` instance). Updates from the view to the model and from the model to the view are synchronous and aren't dependent on the UI rendered. The diagrams below use the same favorite color example to demonstrate how data flows when an input field's value is changed from the view and then from the model.
<figure>
<img src="generated/images/guide/forms-overview/dataflow-reactive-forms-vtm.png" alt="Reactive forms data flow - view to model" width="100%">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/forms-overview/dataflow-reactive-forms-vtm.png" alt="Reactive forms data flow - view to model" width="100%">
</div>
</figure>
The steps below outline the data flow from view to model.
@ -110,8 +116,10 @@ The steps below outline the data flow from view to model.
1. The `FormControl` instance emits the new value through the `valueChanges` observable.
1. Any subscribers to the `valueChanges` observable receive the new value.
<figure>
<img src="generated/images/guide/forms-overview/dataflow-reactive-forms-mtv.png" alt="Reactive forms data flow - model to view" width="100%">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/forms-overview/dataflow-reactive-forms-mtv.png" alt="Reactive forms data flow - model to view" width="100%">
</div>
</figure>
The steps below outline the data flow from model to view.
@ -125,8 +133,10 @@ The steps below outline the data flow from model to view.
In template-driven forms, each form element is linked to a directive that manages the form model internally. The diagrams below use the same favorite color example to demonstrate how data flows when an input field's value is changed from the view and then from the model.
<figure>
<img src="generated/images/guide/forms-overview/dataflow-td-forms-vtm.png" alt="Template-driven forms data flow - view to model" width="100%">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/forms-overview/dataflow-td-forms-vtm.png" alt="Template-driven forms data flow - view to model" width="100%">
</div>
</figure>
The steps below outline the data flow from view to model when the input value changes from *Red* to *Blue*.
@ -140,8 +150,10 @@ The steps below outline the data flow from view to model when the input value ch
1. Because the component template uses two-way data binding for the `favoriteColor` property, the `favoriteColor` property in the component
is updated to the value emitted by the `ngModelChange` event (*Blue*).
<figure>
<img src="generated/images/guide/forms-overview/dataflow-td-forms-mtv.png" alt="Template-driven forms data flow - model to view" width="100%">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/forms-overview/dataflow-td-forms-mtv.png" alt="Template-driven forms data flow - model to view" width="100%">
</div>
</figure>
The steps below outline the data flow from model to view when the `favoriteColor` changes from *Blue* to *Red*.

View File

@ -45,8 +45,10 @@ otherwise wrestle with yourself.
You'll learn to build a template-driven form that looks like this:
<figure>
<img src="generated/images/guide/forms/hero-form-1.png" alt="Clean Form">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/forms/hero-form-1.png" alt="Clean Form">
</div>
</figure>
The *Hero Employment Agency* uses this form to maintain personal information about heroes.
@ -56,8 +58,10 @@ Two of the three fields on this form are required. Required fields have a green
If you delete the hero name, the form displays a validation error in an attention-grabbing style:
<figure>
<img src="generated/images/guide/forms/hero-form-2.png" alt="Invalid, Name Required">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/forms/hero-form-2.png" alt="Invalid, Name Required">
</div>
</figure>
Note that the *Submit* button is disabled, and the "required" bar to the left of the input control changes from green to red.
@ -272,8 +276,10 @@ you display its name using the interpolation syntax.
Running the app right now would be disappointing.
<figure>
<img src="generated/images/guide/forms/hero-form-3.png" alt="Early form with no binding">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/forms/hero-form-3.png" alt="Early form with no binding">
</div>
</figure>
@ -335,8 +341,10 @@ adding and deleting characters, you'd see them appear and disappear
from the interpolated text.
At some point it might look like this:
<figure>
<img src="generated/images/guide/forms/ng-model-in-action.png" alt="ngModel in action">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/forms/ng-model-in-action.png" alt="ngModel in action">
</div>
</figure>
The diagnostic is evidence that values really are flowing from the input box to the model and
@ -383,8 +391,10 @@ After revision, the core of the form should look like this:
If you run the app now and change every hero model property, the form might display like this:
<figure>
<img src="generated/images/guide/forms/ng-model-in-action-2.png" alt="ngModel in action">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/forms/ng-model-in-action-2.png" alt="ngModel in action">
</div>
</figure>
The diagnostic near the top of the form
@ -483,14 +493,18 @@ Follow these steps *precisely*:
The actions and effects are as follows:
<figure>
<img src="generated/images/guide/forms/control-state-transitions-anim.gif" alt="Control State Transition">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/forms/control-state-transitions-anim.gif" alt="Control State Transition">
</div>
</figure>
You should see the following transitions and class names:
<figure>
<img src="generated/images/guide/forms/ng-control-class-changes.png" alt="Control state transitions">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/forms/ng-control-class-changes.png" alt="Control state transitions">
</div>
</figure>
The `ng-valid`/`ng-invalid` pair is the most interesting, because you want to send a
@ -504,8 +518,10 @@ To create such visual feedback, add definitions for the `ng-*` CSS classes.
You can mark required fields and invalid data at the same time with a colored bar
on the left of the input box:
<figure>
<img src="generated/images/guide/forms/validity-required-indicator.png" alt="Invalid Form">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/forms/validity-required-indicator.png" alt="Invalid Form">
</div>
</figure>
You achieve this effect by adding these class definitions to a new `forms.css` file
@ -525,8 +541,10 @@ Leverage the control's state to reveal a helpful message.
When the user deletes the name, the form should look like this:
<figure>
<img src="generated/images/guide/forms/name-required-error.png" alt="Name required">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/forms/name-required-error.png" alt="Name required">
</div>
</figure>
To achieve this effect, extend the `<input>` tag with the following:

View File

@ -111,8 +111,10 @@ directives in `CommonModule`; they dont need to re-install app-wide providers
If you do import `BrowserModule` into a lazy loaded feature module,
Angular returns an error telling you to use `CommonModule` instead.
<figure>
<img src="generated/images/guide/frequent-ngmodules/browser-module-error.gif" width=750 alt="BrowserModule error">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/frequent-ngmodules/browser-module-error.gif" width=750 alt="BrowserModule error">
</div>
</figure>
<hr />

View File

@ -108,8 +108,10 @@ The following diagram represents the relationship between the
`root` `ModuleInjector` and its parent injectors as the
previous paragraphs describe.
<figure>
<img src="generated/images/guide/dependency-injection/injectors.svg" alt="NullInjector, ModuleInjector, root injector">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/dependency-injection/injectors.svg" alt="NullInjector, ModuleInjector, root injector">
</div>
</figure>
While the name `root` is a special alias, other `ModuleInjector`s
@ -1097,8 +1099,10 @@ Each tax return component has the following characteristics:
* Has the ability to save the changes to its tax return or cancel them.
<figure>
<img src="generated/images/guide/dependency-injection/hid-heroes-anim.gif" alt="Heroes in action">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/dependency-injection/hid-heroes-anim.gif" alt="Heroes in action">
</div>
</figure>
Suppose that the `HeroTaxReturnComponent` had logic to manage and restore changes.
@ -1168,8 +1172,10 @@ that have special capabilities suitable for whatever is going on in component (B
Component (B) is the parent of another component (C) that defines its own, even _more specialized_ provider for `CarService`.
<figure>
<img src="generated/images/guide/dependency-injection/car-components.png" alt="car components">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/dependency-injection/car-components.png" alt="car components">
</div>
</figure>
Behind the scenes, each component sets up its own injector with zero, one, or more providers defined for that component itself.
@ -1179,8 +1185,10 @@ its injector produces an instance of `Car` resolved by injector (C) with an `Eng
`Tires` resolved by the root injector (A).
<figure>
<img src="generated/images/guide/dependency-injection/injector-tree.png" alt="car injector tree">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/dependency-injection/injector-tree.png" alt="car injector tree">
</div>
</figure>

View File

@ -25,8 +25,10 @@ contextual possibilities and hints as you type.
This example shows autocomplete in an interpolation. As you type it out,
you can hit tab to complete.
<figure>
<img src="generated/images/guide/language-service/language-completion.gif" alt="autocompletion">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/language-service/language-completion.gif" alt="autocompletion">
</div>
</figure>
There are also completions within elements. Any elements you have as a component selector will
@ -37,8 +39,10 @@ show up in the completion list.
The Angular Language Service can forewarn you of mistakes in your code.
In this example, Angular doesn't know what `orders` is or where it comes from.
<figure>
<img src="generated/images/guide/language-service/language-error.gif" alt="error checking">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/language-service/language-error.gif" alt="error checking">
</div>
</figure>
### Quick info and navigation
@ -46,8 +50,10 @@ In this example, Angular doesn't know what `orders` is or where it comes from.
The quick-info feature allows you to hover to see where components, directives, modules, and so on come from.
You can then click "Go to definition" or press F12 to go directly to the definition.
<figure>
<img src="generated/images/guide/language-service/language-navigation.gif" alt="navigation">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/language-service/language-navigation.gif" alt="navigation">
</div>
</figure>

View File

@ -91,8 +91,10 @@ ng serve
Then go to `localhost:4200` where you should see “customer-app” and three buttons.
<figure>
<img src="generated/images/guide/lazy-loading-ngmodules/three-buttons.png" width="300" alt="three buttons in the browser">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/lazy-loading-ngmodules/three-buttons.png" width="300" alt="three buttons in the browser">
</div>
</figure>
These buttons work, because the CLI automatically added the routes to the feature modules to the `routes` array in `app.module.ts`.
@ -135,23 +137,29 @@ The other feature module's routing module is configured similarly.
You can check to see that a module is indeed being lazy loaded with the Chrome developer tools. In Chrome, open the dev tools by pressing `Cmd+Option+i` on a Mac or `Ctrl+Shift+j` on a PC and go to the Network Tab.
<figure>
<img src="generated/images/guide/lazy-loading-ngmodules/network-tab.png" width="600" alt="lazy loaded modules diagram">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/lazy-loading-ngmodules/network-tab.png" width="600" alt="lazy loaded modules diagram">
</div>
</figure>
Click on the Orders or Customers button. If you see a chunk appear, everything is wired up properly and the feature module is being lazy loaded. A chunk should appear for Orders and for Customers but will only appear once for each.
<figure>
<img src="generated/images/guide/lazy-loading-ngmodules/chunk-arrow.png" width="600" alt="lazy loaded modules diagram">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/lazy-loading-ngmodules/chunk-arrow.png" width="600" alt="lazy loaded modules diagram">
</div>
</figure>
To see it again, or to test after working in the project, clear everything out by clicking the circle with a line through it in the upper left of the Network Tab:
<figure>
<img src="generated/images/guide/lazy-loading-ngmodules/clear.gif" width="200" alt="lazy loaded modules diagram">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/lazy-loading-ngmodules/clear.gif" width="200" alt="lazy loaded modules diagram">
</div>
</figure>

View File

@ -291,8 +291,10 @@ The peek-a-boo exists to show how Angular calls the hooks in the expected order.
This snapshot reflects the state of the log after the user clicked the *Create...* button and then the *Destroy...* button.
<figure>
<img src="generated/images/guide/lifecycle-hooks/peek-a-boo.png" alt="Peek-a-boo">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/lifecycle-hooks/peek-a-boo.png" alt="Peek-a-boo">
</div>
</figure>
The sequence of log messages follows the prescribed hook calling order:
@ -349,8 +351,10 @@ Here it is attached to the repeated hero `<div>`:
Each spy's birth and death marks the birth and death of the attached hero `<div>`
with an entry in the *Hook Log* as seen here:
<figure>
<img src='generated/images/guide/lifecycle-hooks/spy-directive.gif' alt="Spy Directive">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/lifecycle-hooks/spy-directive.gif' alt="Spy Directive">
</div>
</figure>
Adding a hero results in a new hero `<div>`. The spy's `ngOnInit()` logs that event.
@ -440,8 +444,10 @@ The host `OnChangesParentComponent` binds to them like this:
Here's the sample in action as the user makes changes.
<figure>
<img src='generated/images/guide/lifecycle-hooks/on-changes-anim.gif' alt="OnChanges">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/lifecycle-hooks/on-changes-anim.gif' alt="OnChanges">
</div>
</figure>
The log entries appear as the string value of the *power* property changes.
@ -473,8 +479,10 @@ This code inspects certain _values of interest_, capturing and comparing their c
It writes a special message to the log when there are no substantive changes to the `hero` or the `power`
so you can see how often `DoCheck` is called. The results are illuminating:
<figure>
<img src='generated/images/guide/lifecycle-hooks/do-check-anim.gif' alt="DoCheck">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/lifecycle-hooks/do-check-anim.gif' alt="DoCheck">
</div>
</figure>
While the `ngDoCheck()` hook can detect when the hero's `name` has changed, it has a frightful cost.
@ -527,8 +535,10 @@ for one turn of the browser's JavaScript cycle and that's just long enough.
Here's *AfterView* in action:
<figure>
<img src='generated/images/guide/lifecycle-hooks/after-view-anim.gif' alt="AfterView">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/lifecycle-hooks/after-view-anim.gif' alt="AfterView">
</div>
</figure>
Notice that Angular frequently calls `AfterViewChecked()`, often when there are no changes of interest.
@ -572,8 +582,10 @@ The `<ng-content>` tag is a *placeholder* for the external content.
It tells Angular where to insert that content.
In this case, the projected content is the `<app-child>` from the parent.
<figure>
<img src='generated/images/guide/lifecycle-hooks/projected-child-view.png' alt="Projected Content">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/lifecycle-hooks/projected-child-view.png' alt="Projected Content">
</div>
</figure>
<div class="alert is-helpful">

View File

@ -107,8 +107,10 @@ As you click the button, the displayed date alternates between
"**<samp>Friday, April 15, 1988</samp>**".
<figure>
<img src='generated/images/guide/pipes/date-format-toggle-anim.gif' alt="Date Format Toggle">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/pipes/date-format-toggle-anim.gif' alt="Date Format Toggle">
</div>
</figure>
@ -186,8 +188,10 @@ Now you need a component to demonstrate the pipe.
<code-example path="pipes/src/app/power-booster.component.ts" header="src/app/power-booster.component.ts"></code-example>
<figure>
<img src='generated/images/guide/pipes/power-booster.png' alt="Power Booster">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/pipes/power-booster.png' alt="Power Booster">
</div>
</figure>
@ -230,8 +234,10 @@ your pipe and two-way data binding with `ngModel`.
<figure>
<img src='generated/images/guide/pipes/power-boost-calculator-anim.gif' alt="Power Boost Calculator">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/pipes/power-boost-calculator-anim.gif' alt="Power Boost Calculator">
</div>
</figure>
@ -307,8 +313,10 @@ The Flying Heroes application extends the
code with checkbox switches and additional displays to help you experience these effects.
<figure>
<img src='generated/images/guide/pipes/flying-heroes-anim.gif' alt="Flying Heroes">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/pipes/flying-heroes-anim.gif' alt="Flying Heroes">
</div>
</figure>
@ -486,8 +494,10 @@ both requesting the heroes from the `heroes.json` file.
The component renders as the following:
<figure>
<img src='generated/images/guide/pipes/hero-list.png' alt="Hero List">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/pipes/hero-list.png' alt="Hero List">
</div>
</figure>

View File

@ -64,8 +64,10 @@ The form control assigned to `name` is displayed when the component is added to
<code-example path="reactive-forms/src/app/app.component.1.html" region="app-name-editor" header="src/app/app.component.html (name editor)"></code-example>
<figure>
<img src="generated/images/guide/reactive-forms/name-editor-1.png" alt="Name Editor">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/reactive-forms/name-editor-1.png" alt="Name Editor">
</div>
</figure>
## Managing control values
@ -108,8 +110,10 @@ Update the template with a button to simulate a name update. When you click the
The form model is the source of truth for the control, so when you click the button, the value of the input is changed within the component class, overriding its current value.
<figure>
<img src="generated/images/guide/reactive-forms/name-editor-2.png" alt="Name Editor Update">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/reactive-forms/name-editor-2.png" alt="Name Editor Update">
</div>
</figure>
<div class="alert is-helpful">
@ -188,8 +192,10 @@ To display the `ProfileEditor` component that contains the form, add it to a com
`ProfileEditor` allows you to manage the form control instances for the `firstName` and `lastName` controls within the form group instance.
<figure>
<img src="generated/images/guide/reactive-forms/profile-editor-1.png" alt="Profile Editor">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/reactive-forms/profile-editor-1.png" alt="Profile Editor">
</div>
</figure>
## Creating nested form groups
@ -214,8 +220,10 @@ Add the `address` form group containing the `street`, `city`, `state`, and `zip`
The `ProfileEditor` form is displayed as one group, but the model is broken down further to represent the logical grouping areas.
<figure>
<img src="generated/images/guide/reactive-forms/profile-editor-2.png" alt="Profile Editor Update">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/reactive-forms/profile-editor-2.png" alt="Profile Editor Update">
</div>
</figure>
<div class="alert is-helpful">
@ -346,8 +354,10 @@ Display the current status of `profileForm` using interpolation.
<code-example path="reactive-forms/src/app/profile-editor/profile-editor.component.html" region="display-status" header="src/app/profile-editor/profile-editor.component.html (display status)"></code-example>
<figure>
<img src="generated/images/guide/reactive-forms/profile-editor-3.png" alt="Profile Editor Validation">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/reactive-forms/profile-editor-3.png" alt="Profile Editor Validation">
</div>
</figure>
The **Submit** button is disabled because `profileForm` is invalid due to the required `firstName` form control. After you fill out the `firstName` input, the form becomes valid and the **Submit** button is enabled.
@ -412,8 +422,10 @@ Add the template HTML below after the `<div>` closing the `formGroupName` elemen
The `*ngFor` directive iterates over each form control instance provided by the aliases form array instance. Because form array elements are unnamed, you assign the index to the `i` variable and pass it to each control to bind it to the `formControlName` input.
<figure>
<img src="generated/images/guide/reactive-forms/profile-editor-4.png" alt="Profile Editor Aliases">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/reactive-forms/profile-editor-4.png" alt="Profile Editor Aliases">
</div>
</figure>
Each time a new alias instance is added, the new form array instance is provided its control based on the index. This allows you to track each individual control when calculating the status and value of the root control.

View File

@ -25,8 +25,10 @@ Let's illustrate a router transition animation by navigating between two routes,
</br>
<figure>
<img src="generated/images/guide/animations/route-animation.gif" alt="Animations in action" width="440">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/animations/route-animation.gif" alt="Animations in action" width="440">
</div>
</figure>
## Route configuration

View File

@ -765,16 +765,20 @@ Once the app warms up, you'll see a row of navigation buttons
and the *Heroes* view with its list of heroes.
<figure>
<img src='generated/images/guide/router/hero-list.png' alt="Hero List">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/router/hero-list.png' alt="Hero List">
</div>
</figure>
Select one hero and the app takes you to a hero editing screen.
<figure>
<img src='generated/images/guide/router/hero-detail.png' alt="Crisis Center Detail">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/router/hero-detail.png' alt="Crisis Center Detail">
</div>
</figure>
@ -790,8 +794,10 @@ Angular app navigation updates the browser history as normal web navigation does
Now click the *Crisis Center* link for a list of ongoing crises.
<figure>
<img src='generated/images/guide/router/crisis-center-list.png' alt="Crisis Center List">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/router/crisis-center-list.png' alt="Crisis Center List">
</div>
</figure>
@ -803,8 +809,10 @@ Alter the name of a crisis.
Notice that the corresponding name in the crisis list does _not_ change.
<figure>
<img src='generated/images/guide/router/crisis-center-detail.png' alt="Crisis Center Detail">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/router/crisis-center-detail.png' alt="Crisis Center Detail">
</div>
</figure>
@ -819,8 +827,10 @@ Click the browser back button or the "Heroes" link instead.
Up pops a dialog box.
<figure>
<img src='generated/images/guide/router/confirm-dialog.png' alt="Confirm Dialog">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/router/confirm-dialog.png' alt="Confirm Dialog">
</div>
</figure>
@ -842,8 +852,10 @@ Proceed to the first application milestone.
Begin with a simple version of the app that navigates between two empty views.
<figure>
<img src='generated/images/guide/router/router-1-anim.gif' alt="App in action">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/router/router-1-anim.gif' alt="App in action">
</div>
</figure>
{@a import}
@ -928,8 +940,10 @@ Registering the `RouterModule.forRoot()` in the `AppModule` imports makes the `R
The root `AppComponent` is the application shell. It has a title, a navigation bar with two links, and a router outlet where the router swaps components on and off the page. Here's what you get:
<figure>
<img src='generated/images/guide/router/shell-and-outlet.png' alt="Shell">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/router/shell-and-outlet.png' alt="Shell">
</div>
</figure>
The router outlet serves as a placeholder when the routed components will be rendered below it.
@ -1363,8 +1377,10 @@ from the <live-example name="toh-pt4" title="Tour of Heroes: Services example co
Here's how the user will experience this version of the app:
<figure>
<img src='generated/images/guide/router/router-2-anim.gif' alt="App in action">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/router/router-2-anim.gif' alt="App in action">
</div>
</figure>
@ -1944,8 +1960,10 @@ For example, when returning to the hero-detail.component.ts list from the hero d
it would be nice if the viewed hero was preselected in the list.
<figure>
<img src='generated/images/guide/router/selected-hero.png' alt="Selected hero">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/router/selected-hero.png' alt="Selected hero">
</div>
</figure>
@ -2129,8 +2147,10 @@ Add some styles to apply when the list item is selected.
When the user navigates from the heroes list to the "Magneta" hero and back, "Magneta" appears selected:
<figure>
<img src='generated/images/guide/router/selected-hero.png' alt="Selected List">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/router/selected-hero.png' alt="Selected List">
</div>
</figure>
@ -2523,8 +2543,10 @@ to conform to the following recommended pattern for Angular applications:
If your app had many feature areas, the app component trees might look like this:
<figure>
<img src='generated/images/guide/router/component-tree.png' alt="Component Tree">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/router/component-tree.png' alt="Component Tree">
</div>
</figure>
@ -2789,8 +2811,10 @@ It displays a simple form with a header, an input box for the message,
and two buttons, "Send" and "Cancel".
<figure>
<img src='generated/images/guide/router/contact-popup.png' alt="Contact popup">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/router/contact-popup.png' alt="Contact popup">
</div>
</figure>

View File

@ -359,8 +359,10 @@ When you add a new named schematic to this collection, it is automatically added
In addition to the name and description, each schematic has a `factory` property that identifies the schematics entry point.
In the example, you invoke the schematic's defined functionality by calling the `helloWorld()` function in the main file, `hello-world/index.ts`.
<figure>
<img src="generated/images/guide/schematics/collection-files.gif" alt="overview">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/schematics/collection-files.gif" alt="overview">
</div>
</figure>
Each named schematic in the collection has the following main parts.

View File

@ -118,8 +118,10 @@ Angular recognizes the value as unsafe and automatically sanitizes it, which rem
tag but keeps safe content such as the `<b>` element.
<figure>
<img src='generated/images/guide/security/binding-inner-html.png' alt='A screenshot showing interpolated and bound HTML values'>
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/security/binding-inner-html.png' alt='A screenshot showing interpolated and bound HTML values'>
</div>
</figure>
@ -209,8 +211,10 @@ this, mark the URL value as a trusted URL using the `bypassSecurityTrustUrl` cal
<figure>
<img src='generated/images/guide/security/bypass-security-component.png' alt='A screenshot showing an alert box created from a trusted URL'>
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/security/bypass-security-component.png' alt='A screenshot showing an alert box created from a trusted URL'>
</div>
</figure>

View File

@ -74,8 +74,10 @@ To simulate a network issue, disable network interaction for your application. I
2. Go to the **Network tab**.
3. Check the **Offline box**.
<figure>
<img src="generated/images/guide/service-worker/offline-checkbox.png" alt="The offline checkbox in the Network tab is checked">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/service-worker/offline-checkbox.png" alt="The offline checkbox in the Network tab pis checked">
</div>
</figure>
Now the app has no access to network interaction.
@ -86,8 +88,10 @@ With the addition of an Angular service worker, the application behavior changes
If you look at the Network tab, you can verify that the service worker is active.
<figure>
<img src="generated/images/guide/service-worker/sw-active.png" alt="Requests are marked as from ServiceWorker">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/service-worker/sw-active.png" alt="Requests are marked as from ServiceWorker">
</div>
</figure>
Notice that under the "Size" column, the requests state is `(from ServiceWorker)`. This means that the resources are not being loaded from the network. Instead, they are being loaded from the service worker's cache.
@ -142,8 +146,10 @@ Now look at how the browser and service worker handle the updated application.
1. Open http://localhost:8080 again in the same window. What happens?
<figure>
<img src="generated/images/guide/service-worker/welcome-msg-en.png" alt="It still says Welcome to Service Workers!">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/service-worker/welcome-msg-en.png" alt="It still says Welcome to Service Workers!">
</div>
</figure>
What went wrong? Nothing, actually. The Angular service worker is doing its job and serving the version of the application that it has **installed**, even though there is an update available. In the interest of speed, the service worker doesn't wait to check for updates before it serves the application that it has cached.
@ -152,8 +158,10 @@ If you look at the `http-server` logs, you can see the service worker requesting
2. Refresh the page.
<figure>
<img src="generated/images/guide/service-worker/welcome-msg-fr.png" alt="The text has changed to say Bienvenue à app!">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/service-worker/welcome-msg-fr.png" alt="The text has changed to say Bienvenue à app!">
</div>
</figure>
The service worker installed the updated version of your app *in the background*, and the next time the page is loaded or reloaded, the service worker switches to the latest version.

View File

@ -47,8 +47,10 @@ You can inject the `Title` service into the root `AppComponent` and expose a bin
Bind that method to three anchor tags and voilà!
<figure>
<img src="generated/images/guide/set-document-title/set-title-anim.gif" alt="Set title">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/set-document-title/set-title-anim.gif" alt="Set title">
</div>
</figure>
Here's the complete solution:

View File

@ -104,8 +104,10 @@ to `http://localhost:4200/`.
Your app greets you with a message:
<figure>
<img src='generated/images/guide/setup-local/app-works.png' alt="Welcome to my-app!">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/setup-local/app-works.png' alt="Welcome to my-app!">
</div>
</figure>

View File

@ -125,8 +125,10 @@ The `ngIf` directive doesn't hide elements with CSS. It adds and removes them ph
Confirm that fact using browser developer tools to inspect the DOM.
<figure>
<img src='generated/images/guide/structural-directives/element-not-in-dom.png' alt="ngIf=false element not in DOM">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/structural-directives/element-not-in-dom.png' alt="ngIf=false element not in DOM">
</div>
</figure>
@ -151,8 +153,10 @@ A directive could hide the unwanted paragraph instead by setting its `display` s
While invisible, the element remains in the DOM.
<figure>
<img src='generated/images/guide/structural-directives/element-display-in-dom.png' alt="hidden element still in DOM">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/structural-directives/element-display-in-dom.png' alt="hidden element still in DOM">
</div>
</figure>
@ -211,8 +215,10 @@ Internally, Angular translates the `*ngIf` _attribute_ into a `<ng-template>` _e
The first form is not actually rendered, only the finished product ends up in the DOM.
<figure>
<img src='generated/images/guide/structural-directives/hero-div-in-dom.png' alt="hero div in DOM">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/structural-directives/hero-div-in-dom.png' alt="hero div in DOM">
</div>
</figure>
@ -559,8 +565,10 @@ That's the fate of the middle "Hip!" in the phrase "Hip! Hip! Hooray!".
Angular erases the middle "Hip!", leaving the cheer a bit less enthusiastic.
<figure>
<img src='generated/images/guide/structural-directives/template-rendering.png' alt="template tag rendering">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/structural-directives/template-rendering.png' alt="template tag rendering">
</div>
</figure>
@ -617,8 +625,10 @@ You also have a CSS style rule that happens to apply to a `<span>` within a `<p>
The constructed paragraph renders strangely.
<figure>
<img src='generated/images/guide/structural-directives/bad-paragraph.png' alt="spanned paragraph with bad style">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/structural-directives/bad-paragraph.png' alt="spanned paragraph with bad style">
</div>
</figure>
@ -639,8 +649,10 @@ When you try this,
the drop down is empty.
<figure>
<img src='generated/images/guide/structural-directives/bad-select.png' alt="spanned options don't work">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/structural-directives/bad-select.png' alt="spanned options don't work">
</div>
</figure>
@ -662,8 +674,10 @@ Here's the conditional paragraph again, this time using `<ng-container>`.
It renders properly.
<figure>
<img src='generated/images/guide/structural-directives/good-paragraph.png' alt="ngcontainer paragraph with proper style">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/structural-directives/good-paragraph.png' alt="ngcontainer paragraph with proper style">
</div>
</figure>
@ -678,8 +692,10 @@ Now conditionally exclude a _select_ `<option>` with `<ng-container>`.
The drop down works properly.
<figure>
<img src='generated/images/guide/structural-directives/select-ngcontainer-anim.gif' alt="ngcontainer options work properly">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/structural-directives/select-ngcontainer-anim.gif' alt="ngcontainer options work properly">
</div>
</figure>
<div class="alert is-helpful">
@ -828,8 +844,10 @@ When the `condition` is falsy, the top (A) paragraph appears and the bottom (B)
When the `condition` is truthy, the top (A) paragraph is removed and the bottom (B) paragraph appears.
<figure>
<img src='generated/images/guide/structural-directives/unless-anim.gif' alt="UnlessDirective in action">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/structural-directives/unless-anim.gif' alt="UnlessDirective in action">
</div>
</figure>

View File

@ -969,8 +969,10 @@ template statement on the right.
The following event binding listens for the button's click events, calling
the component's `onSave()` method whenever a click occurs:
<figure>
<img src='generated/images/guide/template-syntax/syntax-diagram.svg' alt="Syntax diagram">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/template-syntax/syntax-diagram.svg' alt="Syntax diagram">
</div>
</figure>
### Target event
@ -1306,8 +1308,10 @@ for example, the following changes the `<input>` value to uppercase:
Here are all variations in action, including the uppercase version:
<figure>
<img src='generated/images/guide/built-in-directives/ng-model-anim.gif' alt="NgModel variations">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/built-in-directives/ng-model-anim.gif' alt="NgModel variations">
</div>
</figure>
<hr/>
@ -1512,8 +1516,10 @@ Here is an illustration of the `trackBy` effect.
* With no `trackBy`, both buttons trigger complete DOM element replacement.
* With `trackBy`, only changing the `id` triggers element replacement.
<figure>
<img src="generated/images/guide/built-in-directives/ngfor-trackby.gif" alt="Animation of trackBy">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/built-in-directives/ngfor-trackby.gif" alt="Animation of trackBy">
</div>
</figure>
@ -1538,8 +1544,10 @@ Angular puts only the selected element into the DOM.
<code-example path="built-in-directives/src/app/app.component.html" region="NgSwitch" header="src/app/app.component.html"></code-example>
<figure>
<img src="generated/images/guide/built-in-directives/ngswitch.gif" alt="Animation of NgSwitch">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/built-in-directives/ngswitch.gif" alt="Animation of NgSwitch">
</div>
</figure>
`NgSwitch` is the controller directive. Bind it to an expression that returns
@ -1695,8 +1703,10 @@ child component. So an `@Input()` allows data to be input _into_ the
child component from the parent component.
<figure>
<img src="generated/images/guide/inputs-outputs/input.svg" alt="Input data flow diagram">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/inputs-outputs/input.svg" alt="Input data flow diagram">
</div>
</figure>
To illustrate the use of `@Input()`, edit these parts of your app:
@ -1742,8 +1752,10 @@ With `@Input()`, Angular passes the value for `currentItem` to the child so that
The following diagram shows this structure:
<figure>
<img src="generated/images/guide/inputs-outputs/input-diagram-target-source.svg" alt="Property binding diagram">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/inputs-outputs/input-diagram-target-source.svg" alt="Property binding diagram">
</div>
</figure>
The target in the square brackets, `[]`, is the property you decorate
@ -1776,8 +1788,10 @@ the child _out_ to the parent.
An `@Output()` property should normally be initialized to an Angular [`EventEmitter`](api/core/EventEmitter) with values flowing out of the component as [events](#event-binding).
<figure>
<img src="generated/images/guide/inputs-outputs/output.svg" alt="Output diagram">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/inputs-outputs/output.svg" alt="Output diagram">
</div>
</figure>
Just like with `@Input()`, you can use `@Output()`
@ -1918,8 +1932,10 @@ The target, `item`, which is an `@Input()` property in the child component class
The following diagram is of an `@Input()` and an `@Output()` on the same
child component and shows the different parts of each:
<figure>
<img src="generated/images/guide/inputs-outputs/input-output-diagram.svg" alt="Input/Output diagram">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/inputs-outputs/input-output-diagram.svg" alt="Input/Output diagram">
</div>
</figure>
As the diagram shows, use inputs and outputs together in the same manner as using them separately. Here, the child selector is `<app-input-output>` with `item` and `deleteRequest` being `@Input()` and `@Output()`

View File

@ -41,8 +41,10 @@ It shows that Karma ran three tests that all passed.
A chrome browser also opens and displays the test output in the "Jasmine HTML Reporter" like this.
<figure>
<img src='generated/images/guide/testing/initial-jasmine-html-reporter.png' alt="Jasmine HTML Reporter in the browser">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/testing/initial-jasmine-html-reporter.png' alt="Jasmine HTML Reporter in the browser">
</div>
</figure>
Most people find this browser output easier to read than the console log.
@ -2260,8 +2262,10 @@ tests with the `RouterTestingModule`.
The `HeroDetailComponent` is a simple view with a title, two hero fields, and two buttons.
<figure>
<img src='generated/images/guide/testing/hero-detail.component.png' alt="HeroDetailComponent in action">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/testing/hero-detail.component.png' alt="HeroDetailComponent in action">
</div>
</figure>
But there's plenty of template complexity even in this simple form.
@ -2689,8 +2693,10 @@ A better solution is to create an artificial test component that demonstrates al
<code-example path="testing/src/app/shared/highlight.directive.spec.ts" region="test-component" header="app/shared/highlight.directive.spec.ts (TestComponent)"></code-example>
<figure>
<img src='generated/images/guide/testing/highlight-directive-spec.png' alt="HighlightDirective spec in action">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/testing/highlight-directive-spec.png' alt="HighlightDirective spec in action">
</div>
</figure>
<div class="alert is-helpful">
@ -2770,8 +2776,10 @@ Debug specs in the browser in the same way that you debug an application.
1. Set a breakpoint in the test.
1. Refresh the browser, and it stops at the breakpoint.
<figure>
<img src='generated/images/guide/testing/karma-1st-spec-debug.png' alt="Karma debugging">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/testing/karma-1st-spec-debug.png' alt="Karma debugging">
</div>
</figure>
<hr>

View File

@ -14,8 +14,10 @@ An asterisk `*` or *wildcard* matches any animation state. This is useful for de
For example, a transition of `open => *` applies when the element's state changes from open to anything else.
<figure>
<img src="generated/images/guide/animations/wildcard-state-500.png" alt="wildcard state expressions">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/animations/wildcard-state-500.png" alt="wildcard state expressions">
</div>
</figure>
Here's another code sample using the wildcard state together with our previous example using the `open` and `closed` states. Instead of defining each state-to-state transition pair, we're now saying that any transition to `closed` takes 1 second, and any transition to `open` takes 0.5 seconds.
@ -32,8 +34,10 @@ Use a double arrow syntax to specify state-to-state transitions in both directio
In our two-state button example, the wildcard isn't that useful because there are only two possible states, `open` and `closed`. Wildcard states are better when an element in one particular state has multiple potential states that it can change to. If our button can change from `open` to either `closed` or something like `inProgress`, using a wildcard state could reduce the amount of coding needed.
<figure>
<img src="generated/images/guide/animations/wildcard-3-states.png" alt="wildcard state with 3 states">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/animations/wildcard-3-states.png" alt="wildcard state with 3 states">
</div>
</figure>
@ -217,8 +221,10 @@ In the previous section, we saw a simple two-state transition. Now we'll create
Angular's `keyframe()` function is similar to keyframes in CSS. Keyframes allow several style changes within a single timing segment. For example, our button, instead of fading, could change color several times over a single 2-second timespan.
<figure>
<img src="generated/images/guide/animations/keyframes-500.png" alt="keyframes">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/animations/keyframes-500.png" alt="keyframes">
</div>
</figure>
The code for this color change might look like this.
@ -231,8 +237,10 @@ Keyframes include an *offset* that defines the point in the animation where each
Defining offsets for keyframes is optional. If you omit them, evenly spaced offsets are automatically assigned. For example, three keyframes without predefined offsets receive offsets of 0, 0.5, and 1. Specifying an offset of 0.8 for the middle transition in the above example might look like this.
<figure>
<img src="generated/images/guide/animations/keyframes-offset-500.png" alt="keyframes with offset">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/animations/keyframes-offset-500.png" alt="keyframes with offset">
</div>
</figure>
The code with offsets specified would be as follows.
@ -252,8 +260,10 @@ Here's an example of using keyframes to create a pulse effect:
* A keyframes sequence inserted in the middle that causes the button to appear to pulsate irregularly over the course of that same 1-second timeframe
<figure>
<img src="generated/images/guide/animations/keyframes-pulsation.png" alt="keyframes with irregular pulsation">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/animations/keyframes-pulsation.png" alt="keyframes with irregular pulsation">
</div>
</figure>
The code snippet for this animation might look like this.

View File

@ -266,8 +266,10 @@ everything work seamlessly:
When you register a downgraded service, you must explicitly specify a *string token* that you want to
use in AngularJS.
<figure>
<img src="generated/images/guide/upgrade/injectors.png" alt="The two injectors in a hybrid application">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/upgrade/injectors.png" alt="The two injectors in a hybrid application">
</div>
</figure>
#### Components and the DOM
@ -302,8 +304,10 @@ ways:
bridges the related concepts of AngularJS transclusion and Angular content
projection together.
<figure>
<img src="generated/images/guide/upgrade/dom.png" alt="DOM element ownership in a hybrid application">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/upgrade/dom.png" alt="DOM element ownership in a hybrid application">
</div>
</figure>
Whenever you use a component that belongs to the other framework, a
@ -347,8 +351,10 @@ AngularJS and Angular approaches. Here's what happens:
every turn of the Angular zone. This also triggers AngularJS change
detection after every event.
<figure>
<img src="generated/images/guide/upgrade/change_detection.png" alt="Change detection in a hybrid application">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/upgrade/change_detection.png" alt="Change detection in a hybrid application">
</div>
</figure>
In practice, you do not need to call `$apply()`,

View File

@ -82,8 +82,10 @@ Here's what the UI displays:
<figure>
<img src='generated/images/guide/user-input/keyup1-anim.gif' alt="key up 1">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/user-input/keyup1-anim.gif' alt="key up 1">
</div>
</figure>
@ -161,8 +163,10 @@ and the component does nothing.
Type something in the input box, and watch the display update with each keystroke.
<figure>
<img src='generated/images/guide/user-input/keyup-loop-back-anim.gif' alt="loop back">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/user-input/keyup-loop-back-anim.gif' alt="loop back">
</div>
</figure>
@ -211,8 +215,10 @@ Then Angular calls the event handler only when the user presses _Enter_.
Here's how it works.
<figure>
<img src='generated/images/guide/user-input/keyup3-anim.gif' alt="key up 3">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/user-input/keyup3-anim.gif' alt="key up 3">
</div>
</figure>
@ -243,8 +249,10 @@ The user can add a hero by typing the hero's name in the input box and
clicking **Add**.
<figure>
<img src='generated/images/guide/user-input/little-tour-anim.gif' alt="Little Tour of Heroes">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/user-input/little-tour-anim.gif' alt="Little Tour of Heroes">
</div>
</figure>

View File

@ -105,14 +105,18 @@ When the "Buy" button is clicked, you'll use the cart service to add the current
1. To see the new "Buy" button, refresh the application and click on a product's name to display its details.
<figure>
<img src='generated/images/guide/start/product-details-buy.png' alt="Display details for selected product with a Buy button">
</figure>
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/start/product-details-buy.png' alt="Display details for selected product with a Buy button">
</div>
</figure>
1. Click the "Buy" button. The product is added to the stored list of items in the cart, and a message is displayed.
1. Click the "Buy" button. The product is added to the stored list of items in the cart, and a message is displayed.
<figure>
<img src='generated/images/guide/start/buy-alert.png' alt="Display details for selected product with a Buy button">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/start/buy-alert.png' alt="Display details for selected product with a Buy button">
</div>
</figure>
@ -150,8 +154,10 @@ We'll create the cart page in two steps:
(Note: The "Checkout" button that we provided in the top-bar component was already configured with a `routerLink` for `/cart`.)
<figure>
<img src='generated/images/guide/start/cart-works.png' alt="Display cart page before customizing">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/start/cart-works.png' alt="Display cart page before customizing">
</div>
</figure>
@ -204,8 +210,10 @@ Services can be used to share data across components:
1. Click "Checkout" to see the cart.
1. To add another product, click "My Store" to return to the product list. Repeat the steps above.
<figure>
<img src='generated/images/guide/start/cart-page-full.png' alt="Cart page with products added">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/start/cart-page-full.png' alt="Cart page with products added">
</div>
</figure>
@ -363,14 +371,18 @@ Now that your app can retrieve shipping data, you'll create a shipping component
Click on the "Checkout" button to see the updated cart. (Remember that changing the app causes the preview to refresh, which empties the cart.)
<figure>
<img src='generated/images/guide/start/cart-empty-with-shipping-prices.png' alt="Cart with link to shipping prices">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/start/cart-empty-with-shipping-prices.png' alt="Cart with link to shipping prices">
</div>
</figure>
Click on the link to navigate to the shipping prices.
<figure>
<img src='generated/images/guide/start/shipping-prices.png' alt="Display shipping prices">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/start/shipping-prices.png' alt="Display shipping prices">
</div>
</figure>

View File

@ -73,8 +73,10 @@ Next, you'll add a checkout form at the bottom of the "Cart" page.
After putting a few items in the cart, users can now review their items, enter name and address, and submit their purchase:
<figure>
<img src='generated/images/guide/start/cart-with-items-and-form.png' alt="Cart page with checkout form">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/start/cart-with-items-and-form.png' alt="Cart page with checkout form">
</div>
</figure>

View File

@ -34,8 +34,10 @@ bar&mdash;containing the store name and
checkout icon&mdash;and the title for a product list.
<figure>
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/start/new-app.png" alt="Starter online store app">
</div>
</figure>
@ -96,8 +98,10 @@ file `product-list.component.html`.
The preview pane immediately updates to display the name of each product in the list.
<figure>
<img src="generated/images/guide/start/template-syntax-product-names.png" alt="Product names added to list">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/start/template-syntax-product-names.png" alt="Product names added to list">
</div>
</figure>
1. To make each product name a link to product details, add the `<a>` element and set its title to be the product's name by using the property binding `[ ]` syntax, as follows:
@ -112,8 +116,10 @@ file `product-list.component.html`.
property value as text; property binding `[ ]` lets you
use the property value in a template expression.
<figure>
<img src="generated/images/guide/start/template-syntax-product-anchor.png" alt="Product name anchor text is product name property">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/start/template-syntax-product-anchor.png" alt="Product name anchor text is product name property">
</div>
</figure>
@ -124,8 +130,10 @@ file `product-list.component.html`.
The app now displays the name and description of each product in the list. Notice that the final product does not have a description paragraph. Because the product's description property is empty, Angular doesn't create the `<p>` element&mdash;including the word "Description".
<figure>
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/start/template-syntax-product-description.png" alt="Product descriptions added to list">
</div>
</figure>
1. Add a button so users can share a product with friends. Bind the button's `click` event to the `share()` method (in `product-list.component.ts`). Event binding uses a set of parentheses, `( )`, around the event, as in the following `<button>` element:
@ -135,14 +143,18 @@ file `product-list.component.html`.
Each product now has a "Share" button:
<figure>
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/start/template-syntax-product-share-button.png" alt="Share button added for each product">
</div>
</figure>
Test the "Share" button:
<figure>
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/start/template-syntax-product-share-alert.png" alt="Alert box indicating product has been shared">
</div>
</figure>
The app now has a product list and sharing feature.
@ -198,8 +210,10 @@ An Angular application comprises a tree of components, in which each Angular com
Currently, the example app has three components:
<figure>
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/start/app-components.png" alt="Online store with three components">
</div>
</figure>
* `app-root` (orange box) is the application shell. This is the first component to load and the parent of all other components. You can think of it as the base page.
@ -228,8 +242,10 @@ The next step is to create a new alert feature that takes a product as an input.
1. Right click on the `app` folder and use the `Angular Generator` to generate a new component named `product-alerts`.
<figure>
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/start/generate-component.png" alt="StackBlitz command to generate component">
</div>
</figure>
The generator creates starter files for all three parts of the component:
@ -277,11 +293,12 @@ The next step is to create a new alert feature that takes a product as an input.
The new product alert component takes a product as input from the product list. With that input, it shows or hides the "Notify Me" button, based on the price of the product. The Phone XL price is over $700, so the "Notify Me" button appears on that product.
<figure>
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/start/product-alert-button.png" alt="Product alert button added to products over $700">
</div>
</figure>
<div class="alert is-helpful">
See [Component Interaction](guide/component-interaction "Components & Templates > Component Interaction") for more information about passing data from a parent to child component, intercepting and acting upon a value from the parent, and detecting and acting on changes to input property values.
@ -323,8 +340,10 @@ To make the "Notify Me" button work, you need to configure two things:
1. Try the "Notify Me" button:
<figure>
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/start/product-alert-notification.png" alt="Product alert notification confirmation dialog">
</div>
</figure>

View File

@ -54,8 +54,10 @@ The app is already set up to use the Angular router and to use routing to naviga
Notice that the URL in the preview window changes. The final segment is `products/1`.
<figure>
<img src="generated/images/guide/start/product-details-works.png" alt="Product details page with updated URL">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/start/product-details-works.png" alt="Product details page with updated URL">
</div>
</figure>
@ -108,8 +110,10 @@ The product details component handles the display of each product. The Angular R
Now, when the user clicks on a name in the product list, the router navigates you to the distinct URL for the product, swaps out the product list component for the product details component, and displays the product details.
<figure>
<img src="generated/images/guide/start/product-details-routed.png" alt="Product details page with updated URL and full details displayed">
<figure class="lightbox">
<div class="card">
<img src="generated/images/guide/start/product-details-routed.png" alt="Product details page with updated URL and full details displayed">
</div>
</figure>

View File

@ -49,8 +49,10 @@ After completing all tutorial steps, the final app will look like this: <live-ex
Here's a visual idea of where this tutorial leads, beginning with the "Dashboard"
view and the most heroic heroes:
<figure>
<img src='generated/images/guide/toh/heroes-dashboard-1.png' alt="Output of heroes dashboard">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/toh/heroes-dashboard-1.png' alt="Output of heroes dashboard">
</div>
</figure>
You can click the two links above the dashboard ("Dashboard" and "Heroes")
@ -59,8 +61,10 @@ to navigate between this Dashboard view and a Heroes view.
If you click the dashboard hero "Magneta," the router opens a "Hero Details" view
where you can change the hero's name.
<figure>
<img src='generated/images/guide/toh/hero-details-1.png' alt="Details of hero in app">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/toh/hero-details-1.png' alt="Details of hero in app">
</div>
</figure>
Clicking the "Back" button returns you to the Dashboard.
@ -68,8 +72,10 @@ Links at the top take you to either of the main views.
If you click "Heroes," the app displays the "Heroes" master list view.
<figure>
<img src='generated/images/guide/toh/heroes-list-2.png' alt="Output of heroes list app">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/toh/heroes-list-2.png' alt="Output of heroes list app">
</div>
</figure>
When you click a different hero name, the read-only mini detail beneath the list reflects the new choice.
@ -79,12 +85,16 @@ editable details of the selected hero.
The following diagram captures all of the navigation options.
<figure>
<img src='generated/images/guide/toh/nav-diagram.png' alt="View navigations">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/toh/nav-diagram.png' alt="View navigations">
</div>
</figure>
Here's the app in action:
<figure>
<img src='generated/images/guide/toh/toh-anim.gif' alt="Tour of Heroes in Action">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/toh/toh-anim.gif' alt="Tour of Heroes in Action">
</div>
</figure>

View File

@ -196,10 +196,10 @@ It's difficult to identify the _selected hero_ in the list when all `<li>` eleme
If the user clicks "Magneta", that hero should render with a distinctive but subtle background color like this:
<figure>
<img src='generated/images/guide/toh/heroes-list-selected.png' alt="Selected hero">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/toh/heroes-list-selected.png' alt="Selected hero">
</div>
</figure>
That _selected hero_ coloring is the work of the `.selected` CSS class in the [styles you added earlier](#styles).

View File

@ -9,10 +9,10 @@ There are new requirements for the Tour of Heroes app:
When youre done, users will be able to navigate the app like this:
<figure>
<img src='generated/images/guide/toh/nav-diagram.png' alt="View navigations">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/toh/nav-diagram.png' alt="View navigations">
</div>
</figure>
## Add the `AppRoutingModule`

View File

@ -513,8 +513,10 @@ That's the job of the [`AsyncPipe`](#asyncpipe) in the template.
Run the app again. In the *Dashboard*, enter some text in the search box.
If you enter characters that match any existing hero names, you'll see something like this.
<figure>
<img src='generated/images/guide/toh/toh-hero-search.png' alt="Hero Search Component">
<figure class="lightbox">
<div class="card">
<img src='generated/images/guide/toh/toh-hero-search.png' alt="Hero Search Component">
</div>
</figure>
## Final code review

View File

@ -18,6 +18,7 @@
@media (max-width: 1300px) {
max-width: 100%;
height: auto;
margin: auto;
}
@media (max-width: 600px) {
@ -40,7 +41,8 @@
border: 1px solid $lightgray;
padding: 32px;
box-sizing: border-box;
display: inline-block;
display: flex;
justify-content: center;
box-shadow: 2px 2px 5px 0 rgba(0, 0, 0, .2);
margin: 16px 0;
@ -56,6 +58,11 @@
border-radius: 4px;
padding: 8px;
background-color: $white;
img {
max-width: 100%;
height: auto;
}
}
}
}