Skip to content
Open
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
6 changes: 3 additions & 3 deletions adev-es/src/app/routing/sub-navigation-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -956,17 +956,17 @@ const DOCS_SUB_NAVIGATION_DATA: NavigationItem[] = [
label: 'Using RxJS with Angular',
children: [
{
label: 'Signals interop',
label: 'Interoperabilidad con signals',
path: 'ecosystem/rxjs-interop',
contentPath: 'ecosystem/rxjs-interop/signals-interop',
},
{
label: 'Component output interop',
label: 'Interoperabilidad con outputs de componentes',
path: 'ecosystem/rxjs-interop/output-interop',
contentPath: 'ecosystem/rxjs-interop/output-interop',
},
{
label: 'Unsubscribing with takeUntilDestroyed',
label: 'Cancelar suscripciones con takeUntilDestroyed',
path: 'ecosystem/rxjs-interop/take-until-destroyed',
contentPath: 'ecosystem/rxjs-interop/take-until-destroyed',
},
Expand Down
50 changes: 50 additions & 0 deletions adev-es/src/content/ecosystem/rxjs-interop/output-interop.en.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# RxJS interop with component and directive outputs

TIP: This guide assumes you're familiar with [component and directive outputs](guide/components/outputs).

The `@angular/rxjs-interop` package offers two APIs related to component and directive outputs.

## Creating an output based on an RxJs Observable

The `outputFromObservable` lets you create a component or directive output that emits based on an RxJS observable:

<docs-code language="ts" highlight="[7]">
import {Directive} from '@angular/core';
import {outputFromObservable} from '@angular/core/rxjs-interop';

@Directive({/*...*/})
class Draggable {
pointerMoves$: Observable<PointerMovements> = listenToPointerMoves();

// Whenever `pointerMoves$` emits, the `pointerMove` event fires.
pointerMove = outputFromObservable(this.pointerMoves$);
}
</docs-code>

The `outputFromObservable` function has special meaning to the Angular compiler. **You may only call `outputFromObservable` in component and directive property initializers.**

When you `subscribe` to the output, Angular automatically forwards the subscription to the underlying observable. Angular stops forwarding values when the component or directive is destroyed.

HELPFUL: Consider using `output()` directly if you can emit values imperatively.

## Creating an RxJS Observable from a component or directive output

The `outputToObservable` function lets you create an RxJS observable from a component output.

<docs-code language="ts" highlight="[11]">
import {outputToObservable} from '@angular/core/rxjs-interop';

@Component(/*...*/)
class CustomSlider {
valueChange = output<number>();
}

// Instance reference to `CustomSlider`.
const slider: CustomSlider = createSlider();

outputToObservable(slider.valueChange) // Observable<number>
.pipe(...)
.subscribe(...);
</docs-code>

HELPFUL: Consider using the `subscribe` method on `OutputRef` directly if it meets your needs.
26 changes: 13 additions & 13 deletions adev-es/src/content/ecosystem/rxjs-interop/output-interop.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# RxJS interop with component and directive outputs
# Interoperabilidad de RxJS con outputs de componentes y directivas

TIP: This guide assumes you're familiar with [component and directive outputs](guide/components/outputs).
CONSEJO: Esta guía supone que ya estás familiarizado con los [outputs de componentes y directivas](guide/components/outputs).

The `@angular/rxjs-interop` package offers two APIs related to component and directive outputs.
El paquete `@angular/rxjs-interop` ofrece dos APIs relacionadas con los outputs de componentes y directivas.

## Creating an output based on an RxJs Observable
## Crear un output basado en un Observable de RxJS

The `outputFromObservable` lets you create a component or directive output that emits based on an RxJS observable:
`outputFromObservable` te permite crear un output de componente o directiva que emite en función de un Observable de RxJS:

<docs-code language="ts" highlight="[7]">
import {Directive} from '@angular/core';
Expand All @@ -16,20 +16,20 @@ import {outputFromObservable} from '@angular/core/rxjs-interop';
class Draggable {
pointerMoves$: Observable<PointerMovements> = listenToPointerMoves();

// Whenever `pointerMoves$` emits, the `pointerMove` event fires.
// Cada vez que `pointerMoves$` emite, se dispara el evento `pointerMove`.
pointerMove = outputFromObservable(this.pointerMoves$);
}
</docs-code>

The `outputFromObservable` function has special meaning to the Angular compiler. **You may only call `outputFromObservable` in component and directive property initializers.**
La función `outputFromObservable` tiene un significado especial para el compilador de Angular. **Solo puedes llamar a `outputFromObservable` en inicializadores de propiedades de componentes y directivas.**

When you `subscribe` to the output, Angular automatically forwards the subscription to the underlying observable. Angular stops forwarding values when the component or directive is destroyed.
Cuando te suscribes (`subscribe`) al output, Angular reenvía automáticamente la suscripción al Observable subyacente. Angular deja de reenviar valores cuando el componente o la directiva se destruye.

HELPFUL: Consider using `output()` directly if you can emit values imperatively.
ÚTIL: Considera usar `output()` directamente si puedes emitir valores de forma imperativa.

## Creating an RxJS Observable from a component or directive output
## Crear un Observable de RxJS a partir de un output de componente o directiva

The `outputToObservable` function lets you create an RxJS observable from a component output.
La función `outputToObservable` te permite crear un Observable de RxJS a partir de un output de componente.

<docs-code language="ts" highlight="[11]">
import {outputToObservable} from '@angular/core/rxjs-interop';
Expand All @@ -39,12 +39,12 @@ class CustomSlider {
valueChange = output<number>();
}

// Instance reference to `CustomSlider`.
// Referencia de instancia a `CustomSlider`.
const slider: CustomSlider = createSlider();

outputToObservable(slider.valueChange) // Observable<number>
.pipe(...)
.subscribe(...);
</docs-code>

HELPFUL: Consider using the `subscribe` method on `OutputRef` directly if it meets your needs.
ÚTIL: Considera usar directamente el método `subscribe` en `OutputRef` si satisface tus necesidades.
135 changes: 135 additions & 0 deletions adev-es/src/content/ecosystem/rxjs-interop/signals-interop.en.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
# RxJS interop with Angular signals

The `@angular/core/rxjs-interop` package offers APIs that help you integrate RxJS and Angular signals.

## Create a signal from an RxJs Observable with `toSignal`

Use the `toSignal` function to create 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.

```ts
import { Component } from '@angular/core';
import { AsyncPipe } from '@angular/common';
import { interval } from 'rxjs';
import { toSignal } from '@angular/core/rxjs-interop';

@Component({
template: `{{ counter() }}`,
})
export class Ticker {
counterObservable = interval(1000);

// Get a `Signal` representing the `counterObservable`'s value.
counter = toSignal(this.counterObservable, {initialValue: 0});
}
```

Like the `async` pipe, `toSignal` subscribes to the Observable immediately, which may trigger side effects. The subscription created by `toSignal` automatically unsubscribes from the given Observable when the component or service which calls `toSignal` is destroyed.

IMPORTANT: `toSignal` creates a subscription. You should avoid calling it repeatedly for the same Observable, and instead reuse the signal it returns.

### Injection context

`toSignal` by default needs to run in an [injection context](guide/di/dependency-injection-context), such as during construction of a component or service. If an injection context is not available, you can manually specify the `Injector` to use instead.

### Initial values

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.

#### The `initialValue` option

As in the example above, you can specify an `initialValue` option with the value the signal should return before the Observable emits for the first time.

#### `undefined` initial values

If you don't provide an `initialValue`, the resulting signal will return `undefined` until the Observable emits. This is similar to the `async` pipe's behavior of returning `null`.

#### The `requireSync` option

Some Observables are guaranteed to emit synchronously, such as `BehaviorSubject`. In those cases, you can specify the `requireSync: true` option.

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.

### `manualCleanup`

By default, `toSignal` automatically unsubscribes from the Observable when the component or service that creates it is destroyed.

To override this behavior, you can pass the `manualCleanup` option. You can use this setting for Observables that complete themselves naturally.

### Error and Completion

If an Observable used in `toSignal` produces an error, that error is thrown when the signal is read.

If an Observable used in `toSignal` completes, the signal continues to return the most recently emitted value before completion.

## Create an RxJS Observable from a signal with `toObservable`

Use the `toObservable` utility to create 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.

```ts
import { Component, signal } from '@angular/core';
import { toObservable } from '@angular/core/rxjs-interop';

@Component(/* ... */)
export class SearchResults {
query: Signal<string> = inject(QueryService).query;
query$ = toObservable(this.query);

results$ = this.query$.pipe(
switchMap(query => this.http.get('/search?q=' + query ))
);
}
```

As the `query` signal changes, the `query$` Observable emits the latest query and triggers a new HTTP request.

### Injection context

`toObservable` by default needs to run in an [injection context](guide/di/dependency-injection-context), such as during construction of a component or service. If an injection context is not available, you can manually specify the `Injector` to use instead.

### Timing of `toObservable`

`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.

Unlike Observables, signals never provide a synchronous notification of changes. Even if you update a signal's value multiple times, `toObservable` will only emit the value after the signal stabilizes.

```ts
const obs$ = toObservable(mySignal);
obs$.subscribe(value => console.log(value));

mySignal.set(1);
mySignal.set(2);
mySignal.set(3);
```

Here, only the last value (3) will be logged.

## Using `rxResource` for async data

IMPORTANT: `rxResource` is [experimental](reference/releases#experimental). It's ready for you to try, but it might change before it is stable.

Angular's [`resource` function](/guide/signals/resource) gives you a way to incorporate async data into your application's signal-based code. Building on top of this pattern, `rxResource` lets you define a resource where the source of your data is defined in terms of an RxJS `Observable`. Instead of accepting a `loader` function, `rxResource` accepts a `stream` function that accepts an RxJS `Observable`.

```typescript
import {Component, inject} from '@angular/core';
import {rxResource} from '@angular/core/rxjs-interop';

@Component(/* ... */)
export class UserProfile {
// This component relies on a service that exposes data through an RxJS Observable.
private userData = inject(MyUserDataClient);

protected userId = input<string>();

private userResource = rxResource({
params: () => this.userId(),

// The `stream` property expects a factory function that returns
// a data stream as an RxJS Observable.
stream: ({params}) => this.userData.load(params.userId),
});
}
```

The `stream` property accepts a factory function for an RxJS `Observable`. This factory function is passed the resource's `params` value and returns an `Observable`. The resource calls this factory function every time the `params` computation produces a new value. See [Resource loaders](/guide/signals/resource#resource-loaders) for more details on the parameters passed to the factory function.

In all other ways, `rxResource` behaves like and provides the same APIs as `resource` for specifying parameters, reading values, checking loading state, and examining errors.
Loading