Skip to content

Commit 4faba5c

Browse files
authored
feat(standalone-apis): update to Angular 14.2 (#17)
1 parent d5c7c47 commit 4faba5c

12 files changed

+235
-114
lines changed

docs/frameworks-and-libraries/storybook.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@
44

55
- [Official documentation: Storybook for Angular](https://storybook.js.org/docs/guides/guide-angular/)
66
- [Official documentation](https://storybook.js.org/docs/basics/introduction/)
7-
- [Learn Storybook: Storybook for Angular tutorial](https://www.learnstorybook.com/angular/en/get-started)
7+
- [Storybook for Angular tutorial](https://storybook.js.org/tutorials/intro-to-storybook/angular/en/get-started/)
88
- [How to Build a Component Library with Angular and Storybook](https://indepth.dev/posts/1041/how-to-build-a-component-library-with-angular-and-storybook)
Lines changed: 4 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,11 @@
11
# Adding top-level routes to a standalone Angular application
22

3-
## Interoperability using the RouterModule
3+
To provide the `Router` service and add top-level routes, pass routes to the `provideRouter` function and add it to the `providers` option for `bootstrapApplication`:
44

5-
As of Angular version 14.0.0-rc.0, there is no dedicated standalone API for the Angular router so we pass `RouterModule.forRoot` to the `importProvidersFrom` function:
6-
7-
```typescript
8-
import { enableProdMode, importProvidersFrom } from "@angular/core";
9-
import { bootstrapApplication } from "@angular/platform-browser";
10-
import { RouterModule, Routes } from "@angular/router";
11-
12-
import { AboutComponent } from "./app/about.component";
13-
import { AppComponent } from "./app/app.component";
14-
import { HomeComponent } from "./app/home.component";
15-
import { environment } from "./environments/environment";
16-
17-
if (environment.production) {
18-
enableProdMode();
19-
}
20-
21-
const routes: Routes = [
22-
{
23-
path: "",
24-
pathMatch: "full",
25-
redirectTo: "home",
26-
},
27-
{
28-
path: "home",
29-
component: HomeComponent,
30-
},
31-
{
32-
path: "about",
33-
component: AboutComponent,
34-
},
35-
];
36-
37-
bootstrapApplication(AppComponent, {
38-
providers: [importProvidersFrom(RouterModule.forRoot(routes))],
39-
}).catch((err) => console.error(err));
40-
```
41-
42-
## Future standalone API
43-
44-
In a future Angular version, a function creating the necessary providers will be available. It might look something like this:
45-
46-
```typescript
5+
```typescript {3,31} title="main.ts"
476
import { enableProdMode } from "@angular/core";
487
import { bootstrapApplication } from "@angular/platform-browser";
49-
import { Routes, withRoutes } from "@angular/router";
8+
import { provideRouter, Routes } from "@angular/router";
509

5110
import { AboutComponent } from "./app/about.component";
5211
import { AppComponent } from "./app/app.component";
@@ -74,6 +33,6 @@ const routes: Routes = [
7433
];
7534

7635
bootstrapApplication(AppComponent, {
77-
providers: [withRoutes(routes)],
36+
providers: [provideRouter(routes)],
7837
}).catch((err) => console.error(err));
7938
```

docs/standalone-apis/bootstrapping-a-standalone-application.md

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@ A standalone Angular application bootstraps a component often called the `AppCom
66

77
The following code block lists a simple `main.ts` file:
88

9-
<!-- TODO(LayZeeDK): support code highlighting -->
10-
11-
```typescript
9+
```typescript {2,11} title="main.ts"
1210
import { enableProdMode } from "@angular/core";
1311
import { bootstrapApplication } from "@angular/platform-browser";
1412

@@ -26,11 +24,12 @@ bootstrapApplication(AppComponent).catch((err) => console.error(err));
2624

2725
To add a root-level provider, we can add it to the `providers` array:
2826

29-
```typescript
27+
```typescript {5,13} title="main.ts"
3028
import { enableProdMode } from "@angular/core";
3129
import { bootstrapApplication } from "@angular/platform-browser";
3230

3331
import { AppComponent } from "./app/app.component";
32+
import { AuthService } from "./app/auth.service";
3433
import { environment } from "./environments/environment";
3534

3635
if (environment.production) {
@@ -46,9 +45,9 @@ bootstrapApplication(AppComponent, {
4645

4746
To provide root-level providers using an NgModule, we pass the NgModule to the `importProvidersFrom` function.
4847

49-
For example, we can provide the `HttpClient`'s dependencies as shown in the following listing:
48+
For example, we can provide the `HttpClient` and its dependencies as shown in the following listing:
5049

51-
```typescript
50+
```typescript {1,2,13} title="main.ts"
5251
import { HttpClientModule } from "@angular/common/http";
5352
import { enableProdMode, importProvidersFrom } from "@angular/core";
5453
import { bootstrapApplication } from "@angular/platform-browser";
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
# Configuring the router using standalone features
2+
3+
## Configuring the router for a standalone application
4+
5+
To configure the `Router`, we pass the `with*` feature provider factories to the `provideRouter` function. The first argument passed must be `Routes` while subsequent arguments are 0..n router features, for example:
6+
7+
```typescript {3,34-37} title="main.ts"
8+
import { enableProdMode } from "@angular/core";
9+
import { bootstrapApplication } from "@angular/platform-browser";
10+
import { PreloadAllModules, provideRouter, Routes, withPreloading, withRouterConfig } from "@angular/router";
11+
12+
import { AboutComponent } from "./app/about.component";
13+
import { AppComponent } from "./app/app.component";
14+
import { HomeComponent } from "./app/home.component";
15+
import { environment } from "./environments/environment";
16+
17+
if (environment.production) {
18+
enableProdMode();
19+
}
20+
21+
const routes: Routes = [
22+
{
23+
path: "",
24+
pathMatch: "full",
25+
redirectTo: "home",
26+
},
27+
{
28+
path: "home",
29+
component: HomeComponent,
30+
},
31+
{
32+
path: "about",
33+
component: AboutComponent,
34+
},
35+
];
36+
37+
bootstrapApplication(AppComponent, {
38+
providers: [
39+
provideRouter(
40+
routes,
41+
withPreloading(PreloadAllModules),
42+
withRouterConfig({
43+
onSameUrlNavigation: "reload",
44+
})
45+
),
46+
],
47+
}).catch((err) => console.error(err));
48+
```
49+
50+
## Router features
51+
52+
Feature providers such as [`RouterFeatures`](https://next.angular.io/api/router/RouterFeatures) are tree-shakable.
53+
54+
The following router feature provider factories are available:
55+
56+
- [withDebugTracing](https://next.angular.io/api/router/withPreloading)
57+
- [withDisabledInitialNavigation](https://next.angular.io/api/router/withDisabledInitialNavigation)
58+
- [withEnabledBlockingInitialNavigation](https://next.angular.io/api/router/withEnabledBlockingInitialNavigation)
59+
- [withInMemoryScrolling](https://next.angular.io/api/router/withInMemoryScrolling)
60+
- [withPreloading](https://next.angular.io/api/router/withPreloading)
61+
- [withRouterConfig](https://next.angular.io/api/router/withRouterConfig)
62+
63+
## Configuring the router for component tests
64+
65+
As of Angular version 14.2.0-rc.0, there is no standalone router provider factory for testing.
66+
67+
Until a standalone router testing provider becomes available, use the `RouterTestingModule`, for example:
68+
69+
```typescript {5,20-23} title="category.component.spec.ts"
70+
import { Component, NgZone } from "@angular/core";
71+
import { TestBed } from "@angular/core/testing";
72+
import { By } from "@angular/platform-browser";
73+
import { Router, RouterOutlet, Routes } from "@angular/router";
74+
import { RouterTestingModule } from "@angular/router/testing";
75+
76+
import { CategoryComponent } from "./category.component";
77+
78+
@Component({
79+
imports: [RouterOutlet],
80+
standalone: true,
81+
template: `<router-outlet></router-outlet>`,
82+
})
83+
class TestAppComponent {}
84+
85+
describe(CategoryComponent.name, () => {
86+
beforeEach(() => {
87+
TestBed.configureTestingModule({
88+
imports: [
89+
RouterTestingModule.withRoutes([{ path: "category/:name", component: CategoryComponent }], {
90+
onSameUrlNavigation: "reload",
91+
preloadingStrategy: PreloadAllModules,
92+
}),
93+
],
94+
});
95+
96+
rootFixture = TestBed.createComponent(TestAppComponent);
97+
ngZone = TestBed.inject(NgZone);
98+
router = TestBed.inject(Router);
99+
ngZone!.run(() => router.initialNavigation());
100+
rootFixture.autoDetectChanges();
101+
});
102+
103+
let ngZone: NgZone;
104+
let rootFixture: ComponentFixture<TestAppComponent>;
105+
let router: Router;
106+
107+
it("displays the category title", async () => {
108+
await ngZone!.run(() => router.navigateByUrl("/category/shirts"));
109+
rootFixture.detectChanges();
110+
const title = rootFixture.debugElement.query(By.css("h1")).nativeElement as HTMLElement;
111+
112+
expect(title.textContent?.trim()).toBe("Shirts");
113+
});
114+
});
115+
```
Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,34 @@
11
# Enabling animations in a standalone Angular application
22

3-
## Interoperability using the BrowserAnimationsModule
3+
## Enabling browser animations in a standalone Angular application
44

5-
As of Angular version 14.0.0-rc.0, there is no dedicated standalone API for Angular browser animations so we pass `BrowserAnimationsModule` to the `importProvidersFrom` function:
5+
To enable browser animations in a standalone Angular application, we add the providers returned by the `provideAnimations` provider factory to the `providers` option for the `bootstrapApplication` function:
66

7-
```typescript
8-
import { enableProdMode, importProvidersFrom } from "@angular/core";
7+
```typescript title="main.ts"
8+
import { enableProdMode } from "@angular/core";
9+
import { bootstrapApplication } from "@angular/platform-browser";
10+
import { provideAnimations } from "@angular/platform-browser/animations";
11+
12+
import { AppComponent } from "./app/app.component";
13+
import { environment } from "./environments/environment";
14+
15+
if (environment.production) {
16+
enableProdMode();
17+
}
18+
19+
bootstrapApplication(AppComponent, {
20+
providers: [provideAnimations()],
21+
}).catch((err) => console.error(err));
22+
```
23+
24+
## Enabling browser animations in a standalone Angular application
25+
26+
To disable browser animations in a standalone Angular application, we add the providers returned by the `provideAnimations` provider factory to the `providers` option for the `bootstrapApplication` function:
27+
28+
```typescript title="main.ts"
29+
import { enableProdMode } from "@angular/core";
930
import { bootstrapApplication } from "@angular/platform-browser";
10-
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
31+
import { provideNoopAnimations } from "@angular/platform-browser/animations";
1132

1233
import { AppComponent } from "./app/app.component";
1334
import { environment } from "./environments/environment";
@@ -17,27 +38,38 @@ if (environment.production) {
1738
}
1839

1940
bootstrapApplication(AppComponent, {
20-
providers: [importProvidersFrom(BrowserAnimationsModule)],
41+
providers: [provideNoopAnimations()],
2142
}).catch((err) => console.error(err));
2243
```
2344

24-
## Future standalone API
45+
## Conditionally disable browser animations in a standalone Angular application
46+
47+
Let's say we want to enable browser animations when the application is deployed and running but disable browser animations when our Cypress end-to-end test suites are running. We can do this by creating a custom browser animations provider factory that returns the no-op animations provider when the application is running in a Cypress context and the browser animations provider otherwise:
48+
49+
```typescript title="provide-browser-animations.ts"
50+
import { Provider } from "@angular/core";
51+
import { provideAnimations, provideNoopAnimations } from "@angular/platform-browser/animations";
52+
53+
export function provideBrowserAnimations(): Provider[] {
54+
return "Cypress" in (window as any) ? provideNoopAnimations() : provideAnimations();
55+
}
56+
```
2557

26-
In a future Angular version, a function creating the necessary providers will be available. It might look something like this:
58+
Then we add the result of calling our custom animations provider to the `providers` option for the `bootstrapApplication` function:
2759

28-
```typescript
60+
```typescript title="main.ts"
2961
import { enableProdMode } from "@angular/core";
3062
import { bootstrapApplication } from "@angular/platform-browser";
31-
import { withAnimations } from "@angular/platform-browser/animations";
3263

3364
import { AppComponent } from "./app/app.component";
65+
import { provideBrowserAnimations } from "./app/provide-browser-animations";
3466
import { environment } from "./environments/environment";
3567

3668
if (environment.production) {
3769
enableProdMode();
3870
}
3971

4072
bootstrapApplication(AppComponent, {
41-
providers: [withAnimations()],
73+
providers: [provideBrowserAnimations()],
4274
}).catch((err) => console.error(err));
4375
```

0 commit comments

Comments
 (0)