Skip to content

Commit 08b664d

Browse files
dylhunnalxhub
authored andcommitted
docs: Introduce RxJS and Signals interop guide (#50039)
Create a new Signals section on aio, and add an interop guide. PR Close #50039
1 parent 50a4a7c commit 08b664d

File tree

3 files changed

+109
-0
lines changed

3 files changed

+109
-0
lines changed

.pullapprove.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ groups:
205205
'aio/content/guide/architecture-services.md',
206206
'aio/content/guide/architecture.md',
207207
'aio/content/examples/architecture/**/{*,.*}',
208+
'aio/content/guide/rxjs-interop.md',
208209
'aio/content/images/guide/architecture/**/{*,.*}',
209210
'aio/content/guide/attribute-directives.md',
210211
'aio/content/examples/attribute-directives/**/{*,.*}',

aio/content/guide/rxjs-interop.md

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
# RxJS Interop
2+
3+
<div class="alert is-important">
4+
5+
The RxJS Interop package is available for [developer preview](https://angular.io/guide/releases#developer-preview). It's ready for you to try, but it might change before it is stable.
6+
7+
</div>
8+
9+
Angular's `@angular/core/rxjs-interop` package which provides useful utilities to integrate [Angular Signals](/guide/signals) with RxJS Observables.
10+
11+
## `toSignal`
12+
13+
The `toSignal` function creates a signal which tracks the value of an Observable. It behaves similarly to the `async` pipe in templates, but is more flexible and can be used anywhere in an application.
14+
15+
```ts
16+
import { Component } from '@angular/core';
17+
import { AsyncPipe } from '@angular/common';
18+
import { interval } from 'rxjs';
19+
20+
@Component({
21+
template: `{{ counter() }}`,
22+
})
23+
export class Ticker {
24+
counterObservable = interval(1000);
25+
26+
// Get a `Signal` representing the `counterObservable`'s value.
27+
counter = toSignal(this.counterObservable, {initialValue: 0});
28+
}
29+
```
30+
31+
Like the `async` pipe, `toSignal` subscribes to the Observable immediately, which may trigger side effects. The subscription created by
32+
`toSignal` automatically unsubscribes from the given Observable upon destruction of the the component in which `toSignal` is called.
33+
34+
### Initial values
35+
36+
Observables may not produce a value synchronously on subscription, but signals always require a current value. There are several ways to deal with this "initial" value of `toSignal` signals.
37+
38+
#### The `initialValue` option
39+
40+
As in the example above, the `initialValue` option specifies the value the signal should return before the Observable emits for the first time.
41+
42+
#### `undefined` initial values
43+
44+
If `initialValue` is omitted, the signal returned by `toSignal` returns `undefined` until the Observable emits. This is similar to the `async` pipe's behavior of returning `null`.
45+
46+
#### The `requireSync` option
47+
48+
Some Observables are known to emit synchronously, such as `BehaviorSubject`. In those cases, you can specify the `requireSync: true` option.
49+
50+
When `requiredSync` is `true`, `toSignal` enforces that the Observable emits synchronously on subscription. This guarantees that the signal always has a value, and no `undefined` type or initial value is required.
51+
52+
### `manualCleanup`
53+
54+
By default, `toSignal` automatically unsubscribes from the Observable upon destruction of the context in which it's created. For example, if `toSignal` is called during creation of a component, it cleans up its subscription when the component is destroyed.
55+
56+
The `manualCleanup` option disables this automatic cleanup. You can use this setting for Observables that complete themselves naturally.
57+
58+
### Error and Completion
59+
60+
If an Observable used in `toSignal` produces an error, that error is thrown when the signal is read.
61+
62+
If an Observable used in `toSignal` completes, the signal continues to return the most recently emitted value before completion.
63+
64+
## `toObservable`
65+
66+
The `toObservable` utility creates an `Observable` which tracks the value of a signal. The signal's value is monitored with an `effect`, which emits the value to the Observable when it changes.
67+
68+
```ts
69+
import { Component, signal } from '@angular/core';
70+
71+
@Component(...)
72+
export class SearchResults {
73+
query: Signal<string> = inject(QueryService).query;
74+
query$ = toObservable(this.query);
75+
76+
results$ = this.query$.pipe(
77+
switchMap(query => this.http.get('/search?q=' + query ))
78+
);
79+
}
80+
```
81+
82+
As the `query` signal changes, the `query$` Observable emits the latest query and triggers a new HTTP request.
83+
84+
### Injection context
85+
86+
`toObservable` by default needs to run in an injection context, such as during construction of a component or service. If an injection context is not available, an `Injector` can instead be explicitly specified.
87+
88+
### Timing of `toObservable`
89+
90+
`toObservable` uses an effect to track the value of the signal in a `ReplaySubject`. On subscription, the first value (if available) may be emitted synchronously, and all subsequent values will be asynchronous.
91+
92+
Unlike Observables, signals never provide a synchronous notification of changes. Even if your code updates a signal's value multiple times, effects which depend on its value run only after the signal has "settled".
93+
94+
```ts
95+
const obs = toObservable(mySignal);
96+
obs$.subscribe(value => console.log(value));
97+
98+
mySignal.set(1);
99+
mySignal.set(2);
100+
mySignal.set(3);
101+
```
102+
103+
Here, only the last value (3) will be logged.

aio/content/navigation.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,11 @@
695695
"url": "guide/signals",
696696
"title": "Signals",
697697
"tooltip": "Angular signals for optimized change detection"
698+
},
699+
{
700+
"url": "guide/rxjs-interop",
701+
"title": "RxJS Interop for Signals",
702+
"tooltip": "Angular signals and Observable interop"
698703
}
699704
]
700705
}

0 commit comments

Comments
 (0)