Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs(effects): update examples to standalone api #4522

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
59 changes: 14 additions & 45 deletions projects/ngrx.io/content/guide/effects/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,20 @@ In a service-based application, your components interact with data through many

Imagine that your application manages movies. Here is a component that fetches and displays a list of movies.


<code-example header="movies-page.component.ts">

import { Component, inject } from '@angular/core';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're importing inject here I think it's also good to update the snippet to use inject instead of using the constructor.
Do you also want to change this, or should we pick this up in a different PR?

Note: the example of <code-example header="movies.service.ts"> also needs to be updated using injet

import { CommonModule } from '@angular/common';

@Component({
template: `
&lt;li *ngFor="let movie of movies"&gt;
{{ movie.name }}
&lt;/li&gt;
`
standalone: true,
imports: [CommonModule],
})
export class MoviesPageComponent {
movies: Movie[];
Expand Down Expand Up @@ -68,12 +75,18 @@ The component has multiple responsibilities:
Effects handle external data and interactions, allowing your services to be less stateful and only perform tasks related to external interactions. Next, refactor the component to put the shared movie data in the `Store`. Effects handle the fetching of movie data.

<code-example header="movies-page.component.ts">

import { Component, inject } from '@angular/core';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're importing inject here I think it's also good to update the snippet to use inject instead of using the constructor.
Do you also want to change this, or should we pick this up in a different PR?

import { CommonModule } from '@angular/common';

@Component({
template: `
&lt;div *ngFor="let movie of movies$ | async"&gt;
{{ movie.name }}
&lt;/div&gt;
`
`,
standalone: true,
imports: [CommonModule],
})
export class MoviesPageComponent {
movies$: Observable&lt;Movie[]&gt; = this.store.select(state => state.movies);
Expand Down Expand Up @@ -229,31 +242,6 @@ It's recommended to inject all dependencies as effect function arguments for eas

## Registering Root Effects
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can consolidate the Registering Root Effects and Registering Feature Effects into one, as it's the same for the standalone API.
Can you give this a try or do you'd like help with this?
E.g. the text "Registering effects can also be done using the standalone APIs..." also needs to be updated.


After you've written class-based or functional effects, you must register them so the effects start running. To register root-level effects, add the `EffectsModule.forRoot()` method with an array or sequence of effects classes and/or functional effects dictionaries to your `AppModule`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


<code-example header="app.module.ts">
import { NgModule } from '@angular/core';
import { EffectsModule } from '@ngrx/effects';

import { MoviesEffects } from './effects/movies.effects';
import * as actorsEffects from './effects/actors.effects';

@NgModule({
imports: [
EffectsModule.forRoot(MoviesEffects, actorsEffects),
],
})
export class AppModule {}
</code-example>

<div class="alert is-critical">

The `EffectsModule.forRoot()` method must be added to your `AppModule` imports even if you don't register any root-level effects.

</div>

### Using the Standalone API

Registering effects can also be done using the standalone APIs if you are bootstrapping an Angular application using standalone features.

<code-example header="main.ts">
Expand Down Expand Up @@ -281,25 +269,6 @@ Effects start running **immediately** after instantiation to ensure they are lis

## Registering Feature Effects

For feature modules, register your effects by adding the `EffectsModule.forFeature()` method in the `imports` array of your `NgModule`.

<code-example header="admin.module.ts">
import { NgModule } from '@angular/core';
import { EffectsModule } from '@ngrx/effects';

import { MoviesEffects } from './effects/movies.effects';
import * as actorsEffects from './effects/actors.effects';

@NgModule({
imports: [
EffectsModule.forFeature(MoviesEffects, actorsEffects)
],
})
export class MovieModule {}
</code-example>

### Using the Standalone API

Feature-level effects are registered in the `providers` array of the route config. The same `provideEffects()` function is used in root-level and feature-level effects.

<code-example header="movie-routes.ts">
Expand Down
1 change: 1 addition & 0 deletions projects/ngrx.io/content/guide/effects/lifecycle.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ export function effectResubscriptionHandler&gt;T extends Action&lt;(
);
}

- im not sure what should be done with that one
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tink this page needs to undergo some more changes 😅
We could update this example to use bootstrapApplication or leave it as is for later.
(but remove this comment please).

bootstrapApplication(
  AppComponent,
  {
    providers: [
      {
        provide: EFFECTS_ERROR_HANDLER,
        useValue: effectResubscriptionHandler,
      },
      {
        provide: ErrorHandler, 
        useClass: CustomErrorHandler 
      }
    ],
  }
)

@NgModule({
imports: [EffectsModule.forRoot([MoviesEffects])],
providers: [
Expand Down