Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/frameworks-and-libraries/storybook.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@

- [Official documentation: Storybook for Angular](https://storybook.js.org/docs/guides/guide-angular/)
- [Official documentation](https://storybook.js.org/docs/basics/introduction/)
- [Learn Storybook: Storybook for Angular tutorial](https://www.learnstorybook.com/angular/en/get-started)
- [Storybook for Angular tutorial](https://storybook.js.org/tutorials/intro-to-storybook/angular/en/get-started/)
- [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)
Original file line number Diff line number Diff line change
@@ -1,52 +1,11 @@
# Adding top-level routes to a standalone Angular application

## Interoperability using the RouterModule
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`:

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:

```typescript
import { enableProdMode, importProvidersFrom } from "@angular/core";
import { bootstrapApplication } from "@angular/platform-browser";
import { RouterModule, Routes } from "@angular/router";

import { AboutComponent } from "./app/about.component";
import { AppComponent } from "./app/app.component";
import { HomeComponent } from "./app/home.component";
import { environment } from "./environments/environment";

if (environment.production) {
enableProdMode();
}

const routes: Routes = [
{
path: "",
pathMatch: "full",
redirectTo: "home",
},
{
path: "home",
component: HomeComponent,
},
{
path: "about",
component: AboutComponent,
},
];

bootstrapApplication(AppComponent, {
providers: [importProvidersFrom(RouterModule.forRoot(routes))],
}).catch((err) => console.error(err));
```

## Future standalone API

In a future Angular version, a function creating the necessary providers will be available. It might look something like this:

```typescript
```typescript {3,31} title="main.ts"
import { enableProdMode } from "@angular/core";
import { bootstrapApplication } from "@angular/platform-browser";
import { Routes, withRoutes } from "@angular/router";
import { provideRouter, Routes } from "@angular/router";

import { AboutComponent } from "./app/about.component";
import { AppComponent } from "./app/app.component";
Expand Down Expand Up @@ -74,6 +33,6 @@ const routes: Routes = [
];

bootstrapApplication(AppComponent, {
providers: [withRoutes(routes)],
providers: [provideRouter(routes)],
}).catch((err) => console.error(err));
```
11 changes: 5 additions & 6 deletions docs/standalone-apis/bootstrapping-a-standalone-application.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ A standalone Angular application bootstraps a component often called the `AppCom

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

<!-- TODO(LayZeeDK): support code highlighting -->

```typescript
```typescript {2,11} title="main.ts"
import { enableProdMode } from "@angular/core";
import { bootstrapApplication } from "@angular/platform-browser";

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

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

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

import { AppComponent } from "./app/app.component";
import { AuthService } from "./app/auth.service";
import { environment } from "./environments/environment";

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

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

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

```typescript
```typescript {1,2,13} title="main.ts"
import { HttpClientModule } from "@angular/common/http";
import { enableProdMode, importProvidersFrom } from "@angular/core";
import { bootstrapApplication } from "@angular/platform-browser";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# Configuring the router using standalone features

## Configuring the router for a standalone application

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:

```typescript {3,34-37} title="main.ts"
import { enableProdMode } from "@angular/core";
import { bootstrapApplication } from "@angular/platform-browser";
import { PreloadAllModules, provideRouter, Routes, withPreloading, withRouterConfig } from "@angular/router";

import { AboutComponent } from "./app/about.component";
import { AppComponent } from "./app/app.component";
import { HomeComponent } from "./app/home.component";
import { environment } from "./environments/environment";

if (environment.production) {
enableProdMode();
}

const routes: Routes = [
{
path: "",
pathMatch: "full",
redirectTo: "home",
},
{
path: "home",
component: HomeComponent,
},
{
path: "about",
component: AboutComponent,
},
];

bootstrapApplication(AppComponent, {
providers: [
provideRouter(
routes,
withPreloading(PreloadAllModules),
withRouterConfig({
onSameUrlNavigation: "reload",
})
),
],
}).catch((err) => console.error(err));
```

## Router features

Feature providers such as [`RouterFeatures`](https://next.angular.io/api/router/RouterFeatures) are tree-shakable.

The following router feature provider factories are available:

- [withDebugTracing](https://next.angular.io/api/router/withPreloading)
- [withDisabledInitialNavigation](https://next.angular.io/api/router/withDisabledInitialNavigation)
- [withEnabledBlockingInitialNavigation](https://next.angular.io/api/router/withEnabledBlockingInitialNavigation)
- [withInMemoryScrolling](https://next.angular.io/api/router/withInMemoryScrolling)
- [withPreloading](https://next.angular.io/api/router/withPreloading)
- [withRouterConfig](https://next.angular.io/api/router/withRouterConfig)

## Configuring the router for component tests

As of Angular version 14.2.0-rc.0, there is no standalone router provider factory for testing.

Until a standalone router testing provider becomes available, use the `RouterTestingModule`, for example:

```typescript {5,20-23} title="category.component.spec.ts"
import { Component, NgZone } from "@angular/core";
import { TestBed } from "@angular/core/testing";
import { By } from "@angular/platform-browser";
import { Router, RouterOutlet, Routes } from "@angular/router";
import { RouterTestingModule } from "@angular/router/testing";

import { CategoryComponent } from "./category.component";

@Component({
imports: [RouterOutlet],
standalone: true,
template: `<router-outlet></router-outlet>`,
})
class TestAppComponent {}

describe(CategoryComponent.name, () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
RouterTestingModule.withRoutes([{ path: "category/:name", component: CategoryComponent }], {
onSameUrlNavigation: "reload",
preloadingStrategy: PreloadAllModules,
}),
],
});

rootFixture = TestBed.createComponent(TestAppComponent);
ngZone = TestBed.inject(NgZone);
router = TestBed.inject(Router);
ngZone!.run(() => router.initialNavigation());
rootFixture.autoDetectChanges();
});

let ngZone: NgZone;
let rootFixture: ComponentFixture<TestAppComponent>;
let router: Router;

it("displays the category title", async () => {
await ngZone!.run(() => router.navigateByUrl("/category/shirts"));
rootFixture.detectChanges();
const title = rootFixture.debugElement.query(By.css("h1")).nativeElement as HTMLElement;

expect(title.textContent?.trim()).toBe("Shirts");
});
});
```
Original file line number Diff line number Diff line change
@@ -1,13 +1,34 @@
# Enabling animations in a standalone Angular application

## Interoperability using the BrowserAnimationsModule
## Enabling browser animations in a standalone Angular application

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:
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:

```typescript
import { enableProdMode, importProvidersFrom } from "@angular/core";
```typescript title="main.ts"
import { enableProdMode } from "@angular/core";
import { bootstrapApplication } from "@angular/platform-browser";
import { provideAnimations } from "@angular/platform-browser/animations";

import { AppComponent } from "./app/app.component";
import { environment } from "./environments/environment";

if (environment.production) {
enableProdMode();
}

bootstrapApplication(AppComponent, {
providers: [provideAnimations()],
}).catch((err) => console.error(err));
```

## Enabling browser animations in a standalone Angular application

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:

```typescript title="main.ts"
import { enableProdMode } from "@angular/core";
import { bootstrapApplication } from "@angular/platform-browser";
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
import { provideNoopAnimations } from "@angular/platform-browser/animations";

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

bootstrapApplication(AppComponent, {
providers: [importProvidersFrom(BrowserAnimationsModule)],
providers: [provideNoopAnimations()],
}).catch((err) => console.error(err));
```

## Future standalone API
## Conditionally disable browser animations in a standalone Angular application

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:

```typescript title="provide-browser-animations.ts"
import { Provider } from "@angular/core";
import { provideAnimations, provideNoopAnimations } from "@angular/platform-browser/animations";

export function provideBrowserAnimations(): Provider[] {
return "Cypress" in (window as any) ? provideNoopAnimations() : provideAnimations();
}
```

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

```typescript
```typescript title="main.ts"
import { enableProdMode } from "@angular/core";
import { bootstrapApplication } from "@angular/platform-browser";
import { withAnimations } from "@angular/platform-browser/animations";

import { AppComponent } from "./app/app.component";
import { provideBrowserAnimations } from "./app/provide-browser-animations";
import { environment } from "./environments/environment";

if (environment.production) {
enableProdMode();
}

bootstrapApplication(AppComponent, {
providers: [withAnimations()],
providers: [provideBrowserAnimations()],
}).catch((err) => console.error(err));
```
Loading