parent
635aaaa27d
commit
1710fa861c
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
This page provides a conceptual overview of how you can create and publish new libraries to extend Angular functionality.
|
This page provides a conceptual overview of how you can create and publish new libraries to extend Angular functionality.
|
||||||
|
|
||||||
If you find that you need to solve the same problem in more than one app (or want to share your solution with other developers), you have a candidate for a library.
|
If you find that you need to solve the same problem in more than one application (or want to share your solution with other developers), you have a candidate for a library.
|
||||||
A simple example might be a button that sends users to your company website, that would be included in all apps that your company builds.
|
A simple example might be a button that sends users to your company website, that would be included in all applications that your company builds.
|
||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ You can build, test, and lint the project with CLI commands:
|
||||||
ng lint my-lib
|
ng lint my-lib
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Notice that the configured builder for the project is different from the default builder for app projects.
|
Notice that the configured builder for the project is different from the default builder for application projects.
|
||||||
This builder, among other things, ensures that the library is always built with the [AOT compiler](guide/aot-compiler).
|
This builder, among other things, ensures that the library is always built with the [AOT compiler](guide/aot-compiler).
|
||||||
|
|
||||||
To make library code reusable you must define a public API for it. This "user layer" defines what is available to consumers of your library. A user of your library should be able to access public functionality (such as NgModules, service providers and general utility functions) through a single import path.
|
To make library code reusable you must define a public API for it. This "user layer" defines what is available to consumers of your library. A user of your library should be able to access public functionality (such as NgModules, service providers and general utility functions) through a single import path.
|
||||||
|
@ -89,7 +89,7 @@ Here are some things to consider in migrating application functionality to a lib
|
||||||
|
|
||||||
## Integrating with the CLI using code-generation schematics
|
## Integrating with the CLI using code-generation schematics
|
||||||
|
|
||||||
A library typically includes *reusable code* that defines components, services, and other Angular artifacts (pipes, directives, and so on) that you simply import into a project.
|
A library typically includes *reusable code* that defines components, services, and other Angular artifacts (pipes, directives) that you import into a project.
|
||||||
A library is packaged into an npm package for publishing and sharing.
|
A library is packaged into an npm package for publishing and sharing.
|
||||||
This package can also include [schematics](guide/glossary#schematic) that provide instructions for generating or transforming code directly in your project, in the same way that the CLI creates a generic new component with `ng generate component`.
|
This package can also include [schematics](guide/glossary#schematic) that provide instructions for generating or transforming code directly in your project, in the same way that the CLI creates a generic new component with `ng generate component`.
|
||||||
A schematic that is packaged with a library can, for example, provide the Angular CLI with the information it needs to generate a component that configures and uses a particular feature, or set of features, defined in that library.
|
A schematic that is packaged with a library can, for example, provide the Angular CLI with the information it needs to generate a component that configures and uses a particular feature, or set of features, defined in that library.
|
||||||
|
@ -99,13 +99,13 @@ You can create and include the following kinds of schematics:
|
||||||
|
|
||||||
* Include an installation schematic so that `ng add` can add your library to a project.
|
* Include an installation schematic so that `ng add` can add your library to a project.
|
||||||
|
|
||||||
* Include generation schematics in your library so that `ng generate` can scaffold your defined artifacts (components, services, tests, and so on) in a project.
|
* Include generation schematics in your library so that `ng generate` can scaffold your defined artifacts (components, services, tests) in a project.
|
||||||
|
|
||||||
* Include an update schematic so that `ng update` can update your library’s dependencies and provide migrations for breaking changes in new releases.
|
* Include an update schematic so that `ng update` can update your library’s dependencies and provide migrations for breaking changes in new releases.
|
||||||
|
|
||||||
What you include in your library depends on your task.
|
What you include in your library depends on your task.
|
||||||
For example, you could define a schematic to create a dropdown that is pre-populated with canned data to show how to add it to an app.
|
For example, you could define a schematic to create a dropdown that is pre-populated with canned data to show how to add it to an application.
|
||||||
If you want a dropdown that would contain different passed-in values each time, your library could define a schematic to create it with a given configuration. Developers could then use `ng generate` to configure an instance for their own app.
|
If you want a dropdown that would contain different passed-in values each time, your library could define a schematic to create it with a given configuration. Developers could then use `ng generate` to configure an instance for their own application.
|
||||||
|
|
||||||
Suppose you want to read a configuration file and then generate a form based on that configuration.
|
Suppose you want to read a configuration file and then generate a form based on that configuration.
|
||||||
If that form will need additional customization by the developer who is using your library, it might work best as a schematic.
|
If that form will need additional customization by the developer who is using your library, it might work best as a schematic.
|
||||||
|
@ -135,7 +135,6 @@ npm publish
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{@a lib-assets}
|
{@a lib-assets}
|
||||||
|
|
||||||
## Managing assets in a library
|
## Managing assets in a library
|
||||||
|
@ -166,7 +165,7 @@ A linked library will then have its own set of Angular libraries that it uses fo
|
||||||
However, this can cause problems while building or running your application.
|
However, this can cause problems while building or running your application.
|
||||||
|
|
||||||
To get around this problem you can use TypeScript path mapping to tell TypeScript that it should load some modules from a specific location.
|
To get around this problem you can use TypeScript path mapping to tell TypeScript that it should load some modules from a specific location.
|
||||||
List all the peer dependencies that your library uses in the workspace TypeScript configuration file `./tsconfig.json`, and point them at the local copy in the app's `node_modules` folder.
|
List all the peer dependencies that your library uses in the workspace TypeScript configuration file `./tsconfig.json`, and point them at the local copy in the application's `node_modules` folder.
|
||||||
|
|
||||||
```
|
```
|
||||||
{
|
{
|
||||||
|
@ -187,7 +186,7 @@ This mapping ensures that your library always loads the local copies of the modu
|
||||||
|
|
||||||
## Using your own library in apps
|
## Using your own library in apps
|
||||||
|
|
||||||
You don't have to publish your library to the npm package manager in order to use it in your own apps, but you do have to build it first.
|
You don't have to publish your library to the npm package manager in order to use it in your own applications, but you do have to build it first.
|
||||||
|
|
||||||
To use your own library in an app:
|
To use your own library in an app:
|
||||||
|
|
||||||
|
@ -196,14 +195,14 @@ To use your own library in an app:
|
||||||
ng build my-lib
|
ng build my-lib
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
* In your apps, import from the library by name:
|
* In your applications, import from the library by name:
|
||||||
```
|
```
|
||||||
import { myExport } from 'my-lib';
|
import { myExport } from 'my-lib';
|
||||||
```
|
```
|
||||||
|
|
||||||
### Building and rebuilding your library
|
### Building and rebuilding your library
|
||||||
|
|
||||||
The build step is important if you haven't published your library as an npm package and then installed the package back into your app from npm.
|
The build step is important if you haven't published your library as an npm package and then installed the package back into your application from npm.
|
||||||
For instance, if you clone your git repository and run `npm install`, your editor will show the `my-lib` imports as missing if you haven't yet built your library.
|
For instance, if you clone your git repository and run `npm install`, your editor will show the `my-lib` imports as missing if you haven't yet built your library.
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
<div class="alert is-helpful">
|
||||||
|
@ -216,13 +215,13 @@ The Angular CLI uses the `tsconfig` paths to tell the build system where to find
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
If you find that changes to your library are not reflected in your app, your app is probably using an old build of the library.
|
If you find that changes to your library are not reflected in your application, your app is probably using an old build of the library.
|
||||||
|
|
||||||
You can rebuild your library whenever you make changes to it, but this extra step takes time.
|
You can rebuild your library whenever you make changes to it, but this extra step takes time.
|
||||||
*Incremental builds* functionality improves the library-development experience.
|
*Incremental builds* functionality improves the library-development experience.
|
||||||
Every time a file is changed a partial build is performed that emits the amended files.
|
Every time a file is changed a partial build is performed that emits the amended files.
|
||||||
|
|
||||||
Incremental builds can be run as a background process in your dev environment. To take advantage of this feature add the `--watch` flag to the build command:
|
Incremental builds can be run as a background process in your development environment. To take advantage of this feature add the `--watch` flag to the build command:
|
||||||
|
|
||||||
<code-example language="bash">
|
<code-example language="bash">
|
||||||
ng build my-lib --watch
|
ng build my-lib --watch
|
||||||
|
@ -232,13 +231,13 @@ ng build my-lib --watch
|
||||||
|
|
||||||
The CLI `build` command uses a different builder and invokes a different build tool for libraries than it does for applications.
|
The CLI `build` command uses a different builder and invokes a different build tool for libraries than it does for applications.
|
||||||
|
|
||||||
* The build system for apps, `@angular-devkit/build-angular`, is based on `webpack`, and is included in all new Angular CLI projects.
|
* The build system for applications, `@angular-devkit/build-angular`, is based on `webpack`, and is included in all new Angular CLI projects.
|
||||||
* The build system for libraries is based on `ng-packagr`. It is only added to your dependencies when you add a library using `ng generate library my-lib`.
|
* The build system for libraries is based on `ng-packagr`. It is only added to your dependencies when you add a library using `ng generate library my-lib`.
|
||||||
|
|
||||||
The two build systems support different things, and even where they support the same things, they do those things differently.
|
The two build systems support different things, and even where they support the same things, they do those things differently.
|
||||||
This means that the TypeScript source can result in different JavaScript code in a built library than it would in a built application.
|
This means that the TypeScript source can result in different JavaScript code in a built library than it would in a built application.
|
||||||
|
|
||||||
For this reason, an app that depends on a library should only use TypeScript path mappings that point to the *built library*.
|
For this reason, an application that depends on a library should only use TypeScript path mappings that point to the *built library*.
|
||||||
TypeScript path mappings should *not* point to the library source `.ts` files.
|
TypeScript path mappings should *not* point to the library source `.ts` files.
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -72,7 +72,7 @@ Every hero needs a job. This form helps the agency match the right hero with the
|
||||||
The form highlights some design features that make it easier to use. For instance, the two required fields have a green bar on the left to make them easy to spot. These fields have initial values, so the form is valid and the **Submit** button is enabled.
|
The form highlights some design features that make it easier to use. For instance, the two required fields have a green bar on the left to make them easy to spot. These fields have initial values, so the form is valid and the **Submit** button is enabled.
|
||||||
|
|
||||||
As you work with this form, you will learn how to include validation logic, how to customize the presentation with standard CSS, and how to handle error conditions to ensure valid input.
|
As you work with this form, you will learn how to include validation logic, how to customize the presentation with standard CSS, and how to handle error conditions to ensure valid input.
|
||||||
If the user deletes the hero name, for example, the form becomes invalid. The app detects the changed status, and displays a validation error in an attention-grabbing style.
|
If the user deletes the hero name, for example, the form becomes invalid. The application detects the changed status, and displays a validation error in an attention-grabbing style.
|
||||||
In addition, the **Submit** button is disabled, and the "required" bar to the left of the input control changes from green to red.
|
In addition, the **Submit** button is disabled, and the "required" bar to the left of the input control changes from green to red.
|
||||||
|
|
||||||
<div class="lightbox">
|
<div class="lightbox">
|
||||||
|
@ -138,7 +138,7 @@ template using the `<app-hero-form>` tag.
|
||||||
At this point, the form layout is all plain HTML5, with no bindings or directives.
|
At this point, the form layout is all plain HTML5, with no bindings or directives.
|
||||||
|
|
||||||
6. The sample form uses some style classes from [Twitter Bootstrap](https://getbootstrap.com/css/): `container`, `form-group`, `form-control`, and `btn`.
|
6. The sample form uses some style classes from [Twitter Bootstrap](https://getbootstrap.com/css/): `container`, `form-group`, `form-control`, and `btn`.
|
||||||
To use these styles, the app's style sheet imports the library.
|
To use these styles, the application's style sheet imports the library.
|
||||||
|
|
||||||
<code-example path="forms/src/styles.1.css" header="src/styles.css"></code-example>
|
<code-example path="forms/src/styles.1.css" header="src/styles.css"></code-example>
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@ template using the `<app-hero-form>` tag.
|
||||||
|
|
||||||
<code-example path="forms/src/app/hero-form/hero-form.component.html" header="src/app/hero-form/hero-form.component.html (powers)" region="powers"></code-example>
|
<code-example path="forms/src/app/hero-form/hero-form.component.html" header="src/app/hero-form/hero-form.component.html (powers)" region="powers"></code-example>
|
||||||
|
|
||||||
If you run the app right now, you see the list of powers in the selection control. The input elements are not yet bound to data values or events, so they are still blank and have no behavior.
|
If you run the application right now, you see the list of powers in the selection control. The input elements are not yet bound to data values or events, so they are still blank and have no behavior.
|
||||||
|
|
||||||
<div class="lightbox">
|
<div class="lightbox">
|
||||||
<img src="generated/images/guide/forms/hero-form-3.png" alt="Early form with no binding">
|
<img src="generated/images/guide/forms/hero-form-3.png" alt="Early form with no binding">
|
||||||
|
@ -230,7 +230,7 @@ After these revisions, the form template should look like the following:
|
||||||
|
|
||||||
* Each `<input>` element also has the required `name` property that Angular uses to register the control with the form.
|
* Each `<input>` element also has the required `name` property that Angular uses to register the control with the form.
|
||||||
|
|
||||||
If you run the app now and change every hero model property, the form might display like this:
|
If you run the application now and change every hero model property, the form might display like this:
|
||||||
|
|
||||||
<div class="lightbox">
|
<div class="lightbox">
|
||||||
<img src="generated/images/guide/forms/ng-model-in-action-2.png" alt="ngModel in action">
|
<img src="generated/images/guide/forms/ng-model-in-action-2.png" alt="ngModel in action">
|
||||||
|
@ -433,7 +433,7 @@ To let form users add a new hero, you will add a **New Hero** button that respon
|
||||||
|
|
||||||
5. Enter a name and click **New Hero** again.
|
5. Enter a name and click **New Hero** again.
|
||||||
|
|
||||||
Now the app displays a _Name is required_ error message, because the input box is no longer pristine.
|
Now the application displays a _Name is required_ error message, because the input box is no longer pristine.
|
||||||
The form remembers that you entered a name before clicking **New Hero**.
|
The form remembers that you entered a name before clicking **New Hero**.
|
||||||
|
|
||||||
6. To restore the pristine state of the form controls, clear all of the flags imperatively by calling the form's `reset()` method after calling the `newHero()` method.
|
6. To restore the pristine state of the form controls, clear all of the flags imperatively by calling the form's `reset()` method after calling the `newHero()` method.
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
# Overview of Angular libraries
|
# Overview of Angular libraries
|
||||||
|
|
||||||
Many applications need to solve the same general problems, such as presenting a unified user interface, presenting data, and allowing data entry.
|
Many applications need to solve the same general problems, such as presenting a unified user interface, presenting data, and allowing data entry.
|
||||||
Developers can create general solutions for particular domains that can be adapted for re-use in different apps.
|
Developers can create general solutions for particular domains that can be adapted for re-use in different applications.
|
||||||
Such a solution can be built as Angular *libraries* and these libraries can be published and shared as *npm packages*.
|
Such a solution can be built as Angular *libraries* and these libraries can be published and shared as *npm packages*.
|
||||||
|
|
||||||
An Angular library is an Angular [project](guide/glossary#project) that differs from an app in that it cannot run on its own.
|
An Angular library is an Angular [project](guide/glossary#project) that differs from an application in that it cannot run on its own.
|
||||||
A library must be imported and used in an app.
|
A library must be imported and used in an application.
|
||||||
|
|
||||||
Libraries extend Angular's base functionality. For example, to add [reactive forms](guide/reactive-forms) to an app, add the library package using `ng add @angular/forms`, then import the `ReactiveFormsModule` from the `@angular/forms` library in your application code.
|
Libraries extend Angular's base functionality. For example, to add [reactive forms](guide/reactive-forms) to an app, add the library package using `ng add @angular/forms`, then import the `ReactiveFormsModule` from the `@angular/forms` library in your application code.
|
||||||
Similarly, adding the [service worker](guide/service-worker-intro) library to an Angular application is one of the steps for turning an application into a [Progressive Web App](https://developers.google.com/web/progressive-web-apps/) (PWA).
|
Similarly, adding the [service worker](guide/service-worker-intro) library to an Angular application is one of the steps for turning an application into a [Progressive Web App](https://developers.google.com/web/progressive-web-apps/) (PWA).
|
||||||
[Angular Material](https://material.angular.io/) is an example of a large, general-purpose library that provides sophisticated, reusable, and adaptable UI components.
|
[Angular Material](https://material.angular.io/) is an example of a large, general-purpose library that provides sophisticated, reusable, and adaptable UI components.
|
||||||
|
|
||||||
Any app developer can use these and other libraries that have been published as npm packages by the Angular team or by third parties. See [Using Published Libraries](guide/using-libraries).
|
Any application developer can use these and other libraries that have been published as npm packages by the Angular team or by third parties. See [Using Published Libraries](guide/using-libraries).
|
||||||
|
|
||||||
## Creating libraries
|
## Creating libraries
|
||||||
|
|
||||||
|
@ -25,13 +25,13 @@ Whether you decide to package functionality as a library is an architectural dec
|
||||||
Packaging functionality as a library forces the artifacts in the library to be decoupled from the application's business logic.
|
Packaging functionality as a library forces the artifacts in the library to be decoupled from the application's business logic.
|
||||||
This can help to avoid various bad practices or architecture mistakes that can make it difficult to decouple and reuse code in the future.
|
This can help to avoid various bad practices or architecture mistakes that can make it difficult to decouple and reuse code in the future.
|
||||||
|
|
||||||
Putting code into a separate library is more complex than simply putting everything in one app.
|
Putting code into a separate library is more complex than simply putting everything in one application.
|
||||||
It requires more of an investment in time and thought for managing, maintaining, and updating the library.
|
It requires more of an investment in time and thought for managing, maintaining, and updating the library.
|
||||||
This complexity can pay off, however, when the library is being used in multiple apps.
|
This complexity can pay off, however, when the library is being used in multiple applications.
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
Note that libraries are intended to be used by Angular apps.
|
Note that libraries are intended to be used by Angular applications.
|
||||||
To add Angular functionality to non-Angular web apps, you can use [Angular custom elements](guide/elements).
|
To add Angular functionality to non-Angular web applications, you can use [Angular custom elements](guide/elements).
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -25,7 +25,7 @@ Along the way, it highlights key features of the router such as:
|
||||||
* Lazy loading an `NgModule`.
|
* Lazy loading an `NgModule`.
|
||||||
* The `CanLoad` guard (check before loading feature module assets).
|
* The `CanLoad` guard (check before loading feature module assets).
|
||||||
|
|
||||||
This guide proceeds as a sequence of milestones as if you were building the app step-by-step, but assumes you are familiar with basic [Angular concepts](guide/architecture).
|
This guide proceeds as a sequence of milestones as if you were building the application step-by-step, but assumes you are familiar with basic [Angular concepts](guide/architecture).
|
||||||
For a general introduction to angular, see the [Getting Started](start). For a more in-depth overview, see the [Tour of Heroes](tutorial) tutorial.
|
For a general introduction to angular, see the [Getting Started](start). For a more in-depth overview, see the [Tour of Heroes](tutorial) tutorial.
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
@ -52,7 +52,7 @@ The application has three main feature areas:
|
||||||
|
|
||||||
Try it by clicking on this <live-example name="router" title="Hero Employment Agency Live Example">live example link</live-example>.
|
Try it by clicking on this <live-example name="router" title="Hero Employment Agency Live Example">live example link</live-example>.
|
||||||
|
|
||||||
The app renders with a row of navigation buttons and the *Heroes* view with its list of heroes.
|
The application renders with a row of navigation buttons and the *Heroes* view with its list of heroes.
|
||||||
|
|
||||||
|
|
||||||
<div class="lightbox">
|
<div class="lightbox">
|
||||||
|
@ -61,7 +61,7 @@ The app renders with a row of navigation buttons and the *Heroes* view with its
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Select one hero and the app takes you to a hero editing screen.
|
Select one hero and the application takes you to a hero editing screen.
|
||||||
|
|
||||||
<div class="lightbox">
|
<div class="lightbox">
|
||||||
<img src='generated/images/guide/router/hero-detail.png' alt="Crisis Center Detail">
|
<img src='generated/images/guide/router/hero-detail.png' alt="Crisis Center Detail">
|
||||||
|
@ -70,11 +70,11 @@ Select one hero and the app takes you to a hero editing screen.
|
||||||
|
|
||||||
|
|
||||||
Alter the name.
|
Alter the name.
|
||||||
Click the "Back" button and the app returns to the heroes list which displays the changed hero name.
|
Click the "Back" button and the application returns to the heroes list which displays the changed hero name.
|
||||||
Notice that the name change took effect immediately.
|
Notice that the name change took effect immediately.
|
||||||
|
|
||||||
Had you clicked the browser's back button instead of the app's "Back" button, the app would have returned you to the heroes list as well.
|
Had you clicked the browser's back button instead of the application's "Back" button, the app would have returned you to the heroes list as well.
|
||||||
Angular app navigation updates the browser history as normal web navigation does.
|
Angular application navigation updates the browser history as normal web navigation does.
|
||||||
|
|
||||||
Now click the *Crisis Center* link for a list of ongoing crises.
|
Now click the *Crisis Center* link for a list of ongoing crises.
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ The `Admin` and `Login` buttons illustrate other router capabilities covered lat
|
||||||
|
|
||||||
## Milestone 1: Getting started
|
## Milestone 1: Getting started
|
||||||
|
|
||||||
Begin with a basic version of the app that navigates between two empty views.
|
Begin with a basic version of the application that navigates between two empty views.
|
||||||
|
|
||||||
|
|
||||||
<div class="lightbox">
|
<div class="lightbox">
|
||||||
|
@ -221,7 +221,7 @@ The corresponding component template looks like this:
|
||||||
|
|
||||||
### Define a Wildcard route
|
### Define a Wildcard route
|
||||||
|
|
||||||
You've created two routes in the app so far, one to `/crisis-center` and the other to `/heroes`.
|
You've created two routes in the application so far, one to `/crisis-center` and the other to `/heroes`.
|
||||||
Any other URL causes the router to throw an error and crash the app.
|
Any other URL causes the router to throw an error and crash the app.
|
||||||
|
|
||||||
Add a wildcard route to intercept invalid URLs and handle them gracefully.
|
Add a wildcard route to intercept invalid URLs and handle them gracefully.
|
||||||
|
@ -272,8 +272,8 @@ When the application launches, the initial URL in the browser bar is by default:
|
||||||
That doesn't match any of the hard-coded routes which means the router falls through to the wildcard route and displays the `PageNotFoundComponent`.
|
That doesn't match any of the hard-coded routes which means the router falls through to the wildcard route and displays the `PageNotFoundComponent`.
|
||||||
|
|
||||||
The application needs a default route to a valid page.
|
The application needs a default route to a valid page.
|
||||||
The default page for this app is the list of heroes.
|
The default page for this application is the list of heroes.
|
||||||
The app should navigate there as if the user clicked the "Heroes" link or pasted `localhost:4200/heroes` into the address bar.
|
The application should navigate there as if the user clicked the "Heroes" link or pasted `localhost:4200/heroes` into the address bar.
|
||||||
|
|
||||||
Add a `redirect` route that translates the initial relative URL (`''`) to the desired default path (`/heroes`).
|
Add a `redirect` route that translates the initial relative URL (`''`) to the desired default path (`/heroes`).
|
||||||
|
|
||||||
|
@ -298,7 +298,7 @@ In this app, the router should select the route to the `HeroListComponent` only
|
||||||
In this example, the redirect is in a top level route so the *remaining* URL and the *entire* URL are the same thing.
|
In this example, the redirect is in a top level route so the *remaining* URL and the *entire* URL are the same thing.
|
||||||
|
|
||||||
The other possible `pathMatch` value is `'prefix'` which tells the router to match the redirect route when the remaining URL begins with the redirect route's prefix path.
|
The other possible `pathMatch` value is `'prefix'` which tells the router to match the redirect route when the remaining URL begins with the redirect route's prefix path.
|
||||||
This doesn't apply to this sample app because if the `pathMatch` value were `'prefix'`, every URL would match `''`.
|
This doesn't apply to this sample application because if the `pathMatch` value were `'prefix'`, every URL would match `''`.
|
||||||
|
|
||||||
Try setting it to `'prefix'` and clicking the `Go to sidekicks` button.
|
Try setting it to `'prefix'` and clicking the `Go to sidekicks` button.
|
||||||
Since that's a bad URL, you should see the "Page not found" page.
|
Since that's a bad URL, you should see the "Page not found" page.
|
||||||
|
@ -317,7 +317,7 @@ In this app, the router should select the route to the `HeroListComponent` only
|
||||||
|
|
||||||
### Milestone 1 wrap up
|
### Milestone 1 wrap up
|
||||||
|
|
||||||
Your sample app can switch between two views when the user clicks a link.
|
Your sample application can switch between two views when the user clicks a link.
|
||||||
|
|
||||||
Milestone 1 has covered how to do the following:
|
Milestone 1 has covered how to do the following:
|
||||||
|
|
||||||
|
@ -327,9 +327,9 @@ Milestone 1 has covered how to do the following:
|
||||||
* Configure the router module with `RouterModule.forRoot()`.
|
* Configure the router module with `RouterModule.forRoot()`.
|
||||||
* Set the router to compose HTML5 browser URLs.
|
* Set the router to compose HTML5 browser URLs.
|
||||||
* Handle invalid routes with a `wildcard` route.
|
* Handle invalid routes with a `wildcard` route.
|
||||||
* Navigate to the default route when the app launches with an empty path.
|
* Navigate to the default route when the application launches with an empty path.
|
||||||
|
|
||||||
The starter app's structure looks like this:
|
The starter application's structure looks like this:
|
||||||
|
|
||||||
<div class='filetree'>
|
<div class='filetree'>
|
||||||
|
|
||||||
|
@ -515,7 +515,7 @@ Here are the files in this milestone.
|
||||||
|
|
||||||
## Milestone 2: *Routing module*
|
## Milestone 2: *Routing module*
|
||||||
|
|
||||||
This milestone shows you how to configure a special-purpose module called a *Routing Module*, which holds your app's routing configuration.
|
This milestone shows you how to configure a special-purpose module called a *Routing Module*, which holds your application's routing configuration.
|
||||||
|
|
||||||
The Routing Module has several characteristics:
|
The Routing Module has several characteristics:
|
||||||
|
|
||||||
|
@ -530,7 +530,7 @@ The Routing Module has several characteristics:
|
||||||
|
|
||||||
The sample routing application does not include routing by default.
|
The sample routing application does not include routing by default.
|
||||||
When you use the [Angular CLI](cli) to create a project that does use routing, set the `--routing` option for the project or app, and for each NgModule.
|
When you use the [Angular CLI](cli) to create a project that does use routing, set the `--routing` option for the project or app, and for each NgModule.
|
||||||
When you create or initialize a new project (using the CLI [`ng new`](cli/new) command) or a new app (using the [`ng generate app`](cli/generate) command), specify the `--routing` option.
|
When you create or initialize a new project (using the CLI [`ng new`](cli/new) command) or a new application (using the [`ng generate app`](cli/generate) command), specify the `--routing` option.
|
||||||
This tells the CLI to include the `@angular/router` npm package and create a file named `app-routing.module.ts`.
|
This tells the CLI to include the `@angular/router` npm package and create a file named `app-routing.module.ts`.
|
||||||
You can then use routing in any NgModule that you add to the project or app.
|
You can then use routing in any NgModule that you add to the project or app.
|
||||||
|
|
||||||
|
@ -554,8 +554,7 @@ Create an `AppRouting` module in the `/app` folder to contain the routing config
|
||||||
ng generate module app-routing --module app --flat
|
ng generate module app-routing --module app --flat
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Import the `CrisisListComponent`, `HeroListComponent`, and `PageNotFoundComponent` symbols
|
Import the `CrisisListComponent`, `HeroListComponent`, and `PageNotFoundComponent` symbols like you did in the `app.module.ts`.
|
||||||
just like you did in the `app.module.ts`.
|
|
||||||
Then move the `Router` imports and routing configuration, including `RouterModule.forRoot()`, into this routing module.
|
Then move the `Router` imports and routing configuration, including `RouterModule.forRoot()`, into this routing module.
|
||||||
|
|
||||||
Re-export the Angular `RouterModule` by adding it to the module `exports` array.
|
Re-export the Angular `RouterModule` by adding it to the module `exports` array.
|
||||||
|
@ -583,11 +582,11 @@ The application continues to work just the same, and you can use `AppRoutingModu
|
||||||
|
|
||||||
The routing module, often called the `AppRoutingModule`, replaces the routing configuration in the root or feature module.
|
The routing module, often called the `AppRoutingModule`, replaces the routing configuration in the root or feature module.
|
||||||
|
|
||||||
The routing module is helpful as your app grows and when the configuration includes specialized guard and resolver services.
|
The routing module is helpful as your application grows and when the configuration includes specialized guard and resolver services.
|
||||||
|
|
||||||
Some developers skip the routing module when the configuration is minimal and merge the routing configuration directly into the companion module (for example, `AppModule`).
|
Some developers skip the routing module when the configuration is minimal and merge the routing configuration directly into the companion module (for example, `AppModule`).
|
||||||
|
|
||||||
Most apps should implement a routing module for consistency.
|
Most applications should implement a routing module for consistency.
|
||||||
It keeps the code clean when configuration becomes complex.
|
It keeps the code clean when configuration becomes complex.
|
||||||
It makes testing the feature module easier.
|
It makes testing the feature module easier.
|
||||||
Its existence calls attention to the fact that a module is routed.
|
Its existence calls attention to the fact that a module is routed.
|
||||||
|
@ -599,11 +598,11 @@ It is where developers expect to find and expand routing configuration.
|
||||||
|
|
||||||
This milestone covers the following:
|
This milestone covers the following:
|
||||||
|
|
||||||
* Organizing the app and routes into feature areas using modules.
|
* Organizing the application and routes into feature areas using modules.
|
||||||
* Navigating imperatively from one component to another.
|
* Navigating imperatively from one component to another.
|
||||||
* Passing required and optional information in route parameters.
|
* Passing required and optional information in route parameters.
|
||||||
|
|
||||||
This sample app recreates the heroes feature in the "Services" section of the [Tour of Heroes tutorial](tutorial/toh-pt4 "Tour of Heroes: Services"), and reuses much of the code from the <live-example name="toh-pt4" title="Tour of Heroes: Services example code"></live-example>.
|
This sample application recreates the heroes feature in the "Services" section of the [Tour of Heroes tutorial](tutorial/toh-pt4 "Tour of Heroes: Services"), and reuses much of the code from the <live-example name="toh-pt4" title="Tour of Heroes: Services example code"></live-example>.
|
||||||
|
|
||||||
<!-- KW - this gif isn't ideal for accessibility. Would like to remove it.-->
|
<!-- KW - this gif isn't ideal for accessibility. Would like to remove it.-->
|
||||||
<!-- Here's how the user will experience this version of the app:
|
<!-- Here's how the user will experience this version of the app:
|
||||||
|
@ -615,7 +614,7 @@ This sample app recreates the heroes feature in the "Services" section of the [T
|
||||||
|
|
||||||
A typical application has multiple feature areas, each dedicated to a particular business purpose with its own folder.
|
A typical application has multiple feature areas, each dedicated to a particular business purpose with its own folder.
|
||||||
|
|
||||||
This section shows you how refactor the app into different feature modules, import them into the main module and navigate among them.
|
This section shows you how refactor the application into different feature modules, import them into the main module and navigate among them.
|
||||||
|
|
||||||
|
|
||||||
{@a heroes-functionality}
|
{@a heroes-functionality}
|
||||||
|
@ -747,7 +746,7 @@ You tell the detail view which hero to display by including the selected hero's
|
||||||
|
|
||||||
Import the hero components from their new locations in the `src/app/heroes/` folder and define the two hero routes.
|
Import the hero components from their new locations in the `src/app/heroes/` folder and define the two hero routes.
|
||||||
|
|
||||||
Now that you have routes for the `Heroes` module, register them with the `Router` via the `RouterModule` as you did in the `AppRoutingModule`, with an important difference.
|
Now that you have routes for the `Heroes` module, register them with the `Router` using the `RouterModule` as you did in the `AppRoutingModule`, with an important difference.
|
||||||
|
|
||||||
In the `AppRoutingModule`, you used the static `RouterModule.forRoot()` method to register the routes and application level service providers.
|
In the `AppRoutingModule`, you used the static `RouterModule.forRoot()` method to register the routes and application level service providers.
|
||||||
In a feature module you use the static `forChild()` method.
|
In a feature module you use the static `forChild()` method.
|
||||||
|
@ -770,7 +769,7 @@ The updated `HeroesRoutingModule` looks like this:
|
||||||
<div class="alert is-helpful">
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
Consider giving each feature module its own route configuration file.
|
Consider giving each feature module its own route configuration file.
|
||||||
Though the feature routes are currently minimal, routes have a tendency to grow more complex even in small apps.
|
Though the feature routes are currently minimal, routes have a tendency to grow more complex even in small applications.
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -881,7 +880,7 @@ Accordingly, the _link parameters array_ has two items: the routing _path_ and a
|
||||||
The router composes the destination URL from the array like this: `localhost:4200/hero/15`.
|
The router composes the destination URL from the array like this: `localhost:4200/hero/15`.
|
||||||
|
|
||||||
The router extracts the route parameter (`id:15`) from the URL and supplies it to
|
The router extracts the route parameter (`id:15`) from the URL and supplies it to
|
||||||
the `HeroDetailComponent` via the `ActivatedRoute` service.
|
the `HeroDetailComponent` using the `ActivatedRoute` service.
|
||||||
|
|
||||||
|
|
||||||
{@a activated-route-in-action}
|
{@a activated-route-in-action}
|
||||||
|
@ -1031,7 +1030,7 @@ You can access the parameters directly without subscribing or adding observable
|
||||||
|
|
||||||
`snapshot` only gets the initial value of the parameter map with this technique.
|
`snapshot` only gets the initial value of the parameter map with this technique.
|
||||||
Use the observable `paramMap` approach if there's a possibility that the router could re-use the component.
|
Use the observable `paramMap` approach if there's a possibility that the router could re-use the component.
|
||||||
This tutorial sample app uses with the observable `paramMap`.
|
This tutorial sample application uses with the observable `paramMap`.
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -1247,7 +1246,7 @@ When switching between the two routes, the `HeroDetailComponent` and `HeroListCo
|
||||||
|
|
||||||
This section has covered the following:
|
This section has covered the following:
|
||||||
|
|
||||||
* Organizing the app into feature areas.
|
* Organizing the application into feature areas.
|
||||||
* Navigating imperatively from one component to another.
|
* Navigating imperatively from one component to another.
|
||||||
* Passing information along in route parameters and subscribe to them in the component.
|
* Passing information along in route parameters and subscribe to them in the component.
|
||||||
* Importing the feature area NgModule into the `AppModule`.
|
* Importing the feature area NgModule into the `AppModule`.
|
||||||
|
@ -1521,7 +1520,7 @@ Here are the relevant files for this version of the sample application.
|
||||||
|
|
||||||
This section shows you how to add child routes and use relative routing in your app.
|
This section shows you how to add child routes and use relative routing in your app.
|
||||||
|
|
||||||
To add more features to the app's current crisis center, take similar steps as for the heroes feature:
|
To add more features to the application's current crisis center, take similar steps as for the heroes feature:
|
||||||
|
|
||||||
* Create a `crisis-center` subfolder in the `src/app` folder.
|
* Create a `crisis-center` subfolder in the `src/app` folder.
|
||||||
* Copy the files and folders from `app/heroes` into the new `crisis-center` folder.
|
* Copy the files and folders from `app/heroes` into the new `crisis-center` folder.
|
||||||
|
@ -1553,7 +1552,7 @@ This section shows you how to organize the crisis center to conform to the follo
|
||||||
* Each area root component has its own router outlet and child routes.
|
* Each area root component has its own router outlet and child routes.
|
||||||
* Feature area routes rarely (if ever) cross with routes of other features.
|
* Feature area routes rarely (if ever) cross with routes of other features.
|
||||||
|
|
||||||
If your app had many feature areas, the app component trees might look like this:
|
If your application had many feature areas, the app component trees might look like this:
|
||||||
|
|
||||||
|
|
||||||
<div class="lightbox">
|
<div class="lightbox">
|
||||||
|
@ -1902,7 +1901,7 @@ Setting the popup `RouterOutlet` to `null` clears the outlet and removes the sec
|
||||||
|
|
||||||
## Milestone 5: Route guards
|
## Milestone 5: Route guards
|
||||||
|
|
||||||
At the moment, any user can navigate anywhere in the application anytime, but sometimes you need to control access to different parts of your app for various reasons. Some of which may include the following:
|
At the moment, any user can navigate anywhere in the application any time, but sometimes you need to control access to different parts of your app for various reasons. Some of which may include the following:
|
||||||
|
|
||||||
* Perhaps the user is not authorized to navigate to the target component.
|
* Perhaps the user is not authorized to navigate to the target component.
|
||||||
* Maybe the user must login (authenticate) first.
|
* Maybe the user must login (authenticate) first.
|
||||||
|
@ -2232,7 +2231,7 @@ Returning a `UrlTree` tells the `Router` to cancel the current navigation and sc
|
||||||
|
|
||||||
#### Add the `LoginComponent`
|
#### Add the `LoginComponent`
|
||||||
|
|
||||||
You need a `LoginComponent` for the user to log in to the app. After logging in, you'll redirect to the stored URL if available, or use the default URL.
|
You need a `LoginComponent` for the user to log in to the application. After logging in, you'll redirect to the stored URL if available, or use the default URL.
|
||||||
There is nothing new about this component or the way you use it in the router configuration.
|
There is nothing new about this component or the way you use it in the router configuration.
|
||||||
|
|
||||||
<code-example language="sh">
|
<code-example language="sh">
|
||||||
|
@ -2294,13 +2293,13 @@ instead of adding the `AuthGuard` to each route individually.
|
||||||
|
|
||||||
### `CanDeactivate`: handling unsaved changes
|
### `CanDeactivate`: handling unsaved changes
|
||||||
|
|
||||||
Back in the "Heroes" workflow, the app accepts every change to a hero immediately without validation.
|
Back in the "Heroes" workflow, the application accepts every change to a hero immediately without validation.
|
||||||
|
|
||||||
In the real world, you might have to accumulate the users changes, validate across fields, validate on the server, or hold changes in a pending state until the user confirms them as a group or cancels and reverts all changes.
|
In the real world, you might have to accumulate the users changes, validate across fields, validate on the server, or hold changes in a pending state until the user confirms them as a group or cancels and reverts all changes.
|
||||||
|
|
||||||
When the user navigates away, you can let the user decide what to do with unsaved changes.
|
When the user navigates away, you can let the user decide what to do with unsaved changes.
|
||||||
If the user cancels, you'll stay put and allow more changes.
|
If the user cancels, you'll stay put and allow more changes.
|
||||||
If the user approves, the app can save.
|
If the user approves, the application can save.
|
||||||
|
|
||||||
You still might delay navigation until the save succeeds.
|
You still might delay navigation until the save succeeds.
|
||||||
If you let the user move to the next screen immediately and saving were to fail (perhaps the data is ruled invalid), you would lose the context of the error.
|
If you let the user move to the next screen immediately and saving were to fail (perhaps the data is ruled invalid), you would lose the context of the error.
|
||||||
|
@ -2315,7 +2314,7 @@ The `CanDeactivate` guard helps you decide what to do with unsaved changes and h
|
||||||
|
|
||||||
Users update crisis information in the `CrisisDetailComponent`.
|
Users update crisis information in the `CrisisDetailComponent`.
|
||||||
Unlike the `HeroDetailComponent`, the user changes do not update the crisis entity immediately.
|
Unlike the `HeroDetailComponent`, the user changes do not update the crisis entity immediately.
|
||||||
Instead, the app updates the entity when the user presses the Save button and discards the changes when the user presses the Cancel button.
|
Instead, the application updates the entity when the user presses the Save button and discards the changes when the user presses the Cancel button.
|
||||||
|
|
||||||
Both buttons navigate back to the crisis list after save or cancel.
|
Both buttons navigate back to the crisis list after save or cancel.
|
||||||
|
|
||||||
|
@ -2323,12 +2322,12 @@ Both buttons navigate back to the crisis list after save or cancel.
|
||||||
|
|
||||||
In this scenario, the user could click the heroes link, cancel, push the browser back button, or navigate away without saving.
|
In this scenario, the user could click the heroes link, cancel, push the browser back button, or navigate away without saving.
|
||||||
|
|
||||||
This example app asks the user to be explicit with a confirmation dialog box that waits asynchronously for the user's
|
This example application asks the user to be explicit with a confirmation dialog box that waits asynchronously for the user's
|
||||||
response.
|
response.
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
You could wait for the user's answer with synchronous, blocking code, however, the app is more responsive—and can do other work—by waiting for the user's answer asynchronously.
|
You could wait for the user's answer with synchronous, blocking code, however, the application is more responsive—and can do other work—by waiting for the user's answer asynchronously.
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -2385,7 +2384,7 @@ Now you have given the user a safeguard against unsaved changes.
|
||||||
|
|
||||||
### _Resolve_: pre-fetching component data
|
### _Resolve_: pre-fetching component data
|
||||||
|
|
||||||
In the `Hero Detail` and `Crisis Detail`, the app waited until the route was activated to fetch the respective hero or crisis.
|
In the `Hero Detail` and `Crisis Detail`, the application waited until the route was activated to fetch the respective hero or crisis.
|
||||||
|
|
||||||
If you were using a real world API, there might be some delay before the data to display is returned from the server.
|
If you were using a real world API, there might be some delay before the data to display is returned from the server.
|
||||||
You don't want to display a blank component while waiting for the data.
|
You don't want to display a blank component while waiting for the data.
|
||||||
|
@ -2556,7 +2555,7 @@ query parameters and fragment.
|
||||||
<code-example path="router/src/app/admin/admin-dashboard/admin-dashboard.component.1.ts" header="src/app/admin/admin-dashboard/admin-dashboard.component.ts (v2)"></code-example>
|
<code-example path="router/src/app/admin/admin-dashboard/admin-dashboard.component.1.ts" header="src/app/admin/admin-dashboard/admin-dashboard.component.ts (v2)"></code-example>
|
||||||
|
|
||||||
Query parameters and fragments are also available through the `ActivatedRoute` service.
|
Query parameters and fragments are also available through the `ActivatedRoute` service.
|
||||||
Just like route parameters, the query parameters and fragments are provided as an `Observable`.
|
Like route parameters, the query parameters and fragments are provided as an `Observable`.
|
||||||
The updated Crisis Admin component feeds the `Observable` directly into the template using the `AsyncPipe`.
|
The updated Crisis Admin component feeds the `Observable` directly into the template using the `AsyncPipe`.
|
||||||
|
|
||||||
Now, you can click on the Admin button, which takes you to the Login page with the provided `queryParamMap` and `fragment`.
|
Now, you can click on the Admin button, which takes you to the Login page with the provided `queryParamMap` and `fragment`.
|
||||||
|
@ -2609,7 +2608,7 @@ Open the `AppRoutingModule` and add a new `admin` route to its `appRoutes` array
|
||||||
|
|
||||||
Give it a `loadChildren` property instead of a `children` property.
|
Give it a `loadChildren` property instead of a `children` property.
|
||||||
The `loadChildren` property takes a function that returns a promise using the browser's built-in syntax for lazy loading code using dynamic imports `import('...')`.
|
The `loadChildren` property takes a function that returns a promise using the browser's built-in syntax for lazy loading code using dynamic imports `import('...')`.
|
||||||
The path is the location of the `AdminModule` (relative to the app root).
|
The path is the location of the `AdminModule` (relative to the application root).
|
||||||
After the code is requested and loaded, the `Promise` resolves an object that contains the `NgModule`, in this case the `AdminModule`.
|
After the code is requested and loaded, the `Promise` resolves an object that contains the `NgModule`, in this case the `AdminModule`.
|
||||||
|
|
||||||
<code-example path="router/src/app/app-routing.module.5.ts" region="admin-1" header="app-routing.module.ts (load children)"></code-example>
|
<code-example path="router/src/app/app-routing.module.5.ts" region="admin-1" header="app-routing.module.ts (load children)"></code-example>
|
||||||
|
@ -2687,7 +2686,7 @@ For the smallest initial payload and fastest launch time, you should eagerly loa
|
||||||
|
|
||||||
You could lazy load the Crisis Center.
|
You could lazy load the Crisis Center.
|
||||||
But you're almost certain that the user will visit the Crisis Center within minutes of launching the app.
|
But you're almost certain that the user will visit the Crisis Center within minutes of launching the app.
|
||||||
Ideally, the app would launch with just the `AppModule` and the `HeroesModule` loaded and then, almost immediately, load the `CrisisCenterModule` in the background.
|
Ideally, the application would launch with just the `AppModule` and the `HeroesModule` loaded and then, almost immediately, load the `CrisisCenterModule` in the background.
|
||||||
By the time the user navigates to the Crisis Center, its module will have been loaded and ready.
|
By the time the user navigates to the Crisis Center, its module will have been loaded and ready.
|
||||||
|
|
||||||
{@a how-preloading}
|
{@a how-preloading}
|
||||||
|
|
|
@ -9,7 +9,7 @@ As users access your application's features, the browser needs to render only th
|
||||||
To define how users navigate through your application, you use routes. You can add routes to define how users navigate from one part of your application to another.
|
To define how users navigate through your application, you use routes. You can add routes to define how users navigate from one part of your application to another.
|
||||||
You can also configure routes to guard against unexpected or unauthorized behavior.
|
You can also configure routes to guard against unexpected or unauthorized behavior.
|
||||||
|
|
||||||
To explore a sample app featuring the contents of this tutorial, see the <live-example></live-example>.
|
To explore a sample application featuring the contents of this tutorial, see the <live-example></live-example>.
|
||||||
|
|
||||||
## Objectives
|
## Objectives
|
||||||
|
|
||||||
|
|
|
@ -8,10 +8,10 @@ See the [Angular Resources](resources) page for links to the most popular ones.
|
||||||
Libraries are published as [npm packages](guide/npm-packages), usually together with schematics that integrate them with the Angular CLI.
|
Libraries are published as [npm packages](guide/npm-packages), usually together with schematics that integrate them with the Angular CLI.
|
||||||
To integrate reusable library code into an application, you need to install the package and import the provided functionality where you will use it. For most published Angular libraries, you can use the Angular CLI `ng add <lib_name>` command.
|
To integrate reusable library code into an application, you need to install the package and import the provided functionality where you will use it. For most published Angular libraries, you can use the Angular CLI `ng add <lib_name>` command.
|
||||||
|
|
||||||
The `ng add` command uses a package manager such as [npm](https://www.npmjs.com/) or [yarn](https://yarnpkg.com/) to install the library package, and invokes schematics that are included in the package to other scaffolding within the project code, such as adding import statements, fonts, themes, and so on.
|
The `ng add` command uses a package manager such as [npm](https://www.npmjs.com/) or [yarn](https://yarnpkg.com/) to install the library package, and invokes schematics that are included in the package to other scaffolding within the project code, such as adding import statements, fonts, and themes.
|
||||||
|
|
||||||
A published library typically provides a README or other documentation on how to add that lib to your app.
|
A published library typically provides a README or other documentation on how to add that lib to your application.
|
||||||
For an example, see [Angular Material](https://material.angular.io/) docs.
|
For an example, see the [Angular Material](https://material.angular.io/) documents.
|
||||||
|
|
||||||
### Library typings
|
### Library typings
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ See the [Angular Update Guide](https://update.angular.io/) for help.
|
||||||
|
|
||||||
## Adding a library to the runtime global scope
|
## Adding a library to the runtime global scope
|
||||||
|
|
||||||
Legacy JavaScript libraries that are not imported into an app can be added to the runtime global scope and loaded as if they were in a script tag.
|
Legacy JavaScript libraries that are not imported into an application can be added to the runtime global scope and loaded as if they were in a script tag.
|
||||||
Configure the CLI to do this at build time using the "scripts" and "styles" options of the build target in the [CLI configuration file](guide/workspace-config), `angular.json`.
|
Configure the CLI to do this at build time using the "scripts" and "styles" options of the build target in the [CLI configuration file](guide/workspace-config), `angular.json`.
|
||||||
|
|
||||||
For example, to use the [Bootstrap 4](https://getbootstrap.com/docs/4.0/getting-started/introduction/) library, first install the library and its dependencies using the npm package manager:
|
For example, to use the [Bootstrap 4](https://getbootstrap.com/docs/4.0/getting-started/introduction/) library, first install the library and its dependencies using the npm package manager:
|
||||||
|
@ -97,7 +97,7 @@ Add the Bootstrap CSS file to the "styles" array:
|
||||||
],
|
],
|
||||||
```
|
```
|
||||||
|
|
||||||
Run or restart `ng serve` to see Bootstrap 4 working in your app.
|
Run or restart `ng serve` to see Bootstrap 4 working in your application.
|
||||||
|
|
||||||
### Using runtime-global libraries inside your app
|
### Using runtime-global libraries inside your app
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue