Skip to main content

signal.subscription

Subscribe to GraphQL subscriptions and receive real-time updates via reactive Signals.

API

Apollo.signal.subscription<TData, TVariables>(
options: SignalSubscriptionOptions<TVariables, TData>
): SignalSubscription<TData, TVariables>

Returns a SignalSubscription<TData, TVariables> instance. This object provides reactive Signals (result, data, loading, error, active) reflecting the subscription's state. It also includes methods execute (for lazy subscriptions) and terminate.

Options
PropertyTypeDescription
subscriptionDocumentNode | TypedDocumentNode<TData, TVariables>A GraphQL document, often created with gql from the graphql-tag
package, that contains a single subscription inside of it.
fetchPolicy?FetchPolicyHow you want your component to interact with the Apollo cache. For details, see Setting a fetch policy.
errorPolicy?ErrorPolicySpecifies the ErrorPolicy to be used for this operation
context?DefaultContextShared context between your component and your network interface (Apollo Link).
extensions?Record<string, any>Shared context between your component and your network interface (Apollo Link).
lazy?booleanWhether to execute subscription immediately or lazily via execute method.
onData?(data: TData) => voidCallback for when new data is received
onComplete?() => voidCallback for when the subscription is completed
onError?(error: ErrorLike) => voidCallback for when an error occurs
injector?InjectorCustom injector to use for this subscription.
variables?() => TVariables | undefined | A function or signal returning an object containing all of the GraphQL variables your operation requires to execute.

Each key in the object corresponds to a variable name, and that key's value corresponds to the variable value.*

When null is returned, the subscription will be terminated until a non-null value is returned again.
Signals
SignalTypeDescription
resultSignal<SignalSubscriptionResult<TData>>The subscription result, containing data, loading, and error.
loadingSignal<boolean>If true, the subscription is currently loading the initial result.
dataSignal<TData | undefined>The data returned by the subscription, or undefined if loading, errored, or no data received yet.
errorSignal<ErrorLike | undefined>An error object if the subscription failed, undefined otherwise.
activeSignal<boolean>Whether the subscription is currently active, connected to the server and receiving real-time updates.
enabledSignal<boolean>Whether the subscription is currently enabled.

This property starts as true for non-lazy subscriptions and false for lazy subscriptions.

Calling execute() sets it to true, while calling terminate() sets it to false.

When true:
- The subscription automatically starts when variables change from null to a non-null value
- Variable changes trigger re-subscription with the new variables

When false:
- Variable changes are ignored and do not trigger re-subscription
- The subscription must be manually started via execute()

Note: This is different from active, which indicates whether the subscription is currently connected to the server and receiving real-time updates.
Methods
MethodDescription
execute(execOptions: SignalSubscriptionExecOptions<TVariables>)Execute subscription.
terminate()Terminate subscription.

Executing a subscription

To execute a subscription within an Angular component using Signals, inject Apollo and call signal.subscription with a GraphQL subscription document. The returned SignalSubscription object's signals can be used directly in your component's template or logic to reactively handle real-time updates.

Let's look at an example using the same subscription from the subscribe guide:

library/authors/authors.component.ts
import { Apollo } from '@apollo-orbit/angular';
import { NEW_AUTHOR_SUBSCRIPTION } from '../graphql/types';

@Component({
selector: 'app-authors',
template: `
@if (newAuthorSubscription.data(); as author) {
<div class="alert-info">New author was added: {{ author.newAuthor.name }}</div>
}
@if (newAuthorSubscription.error(); as error) {
<div class="alert-error">Subscription error: {{ error.message }}</div>
}
`
})
export class AuthorsComponent {
private readonly apollo = inject(Apollo);

protected readonly newAuthorSubscription = this.apollo.signal.subscription({
subscription: NEW_AUTHOR_SUBSCRIPTION
});
}

Variables

A variables function or signal may be passed to signal.subscription options. If the function depends on reactive variables, SignalSubscription will automatically update and restart the subscription when these reactive variables change.

library/books/books.component.ts
import { Apollo } from '@apollo-orbit/angular';
import { NEW_BOOK_SUBSCRIPTION } from '../graphql/types';

@Component({
selector: 'app-books',
template: `
<h3>New Books</h3>
@if (newBookSubscription.data(); as data) {
<div class="alert-info">New book added: {{ data.newBook.name }}</div>
}
`
})
export class BooksComponent {
private readonly apollo = inject(Apollo);

// Component input signal
public readonly authorId = input<string>();

protected readonly newBookSubscription = this.apollo.signal.subscription({
subscription: NEW_BOOK_SUBSCRIPTION,
variables: () => ({ authorId: this.authorId() })
});
}

Variables = null

When the variables function returns null, SignalSubscription will automatically terminate the subscription:

library/book/book.component.ts
import { Apollo } from '@apollo-orbit/angular';
import { BOOK_UPDATE_SUBSCRIPTION } from '../graphql/types';

@Component({
selector: 'app-book',
templateUrl: './book.component.html'
})
export class BookComponent {
private readonly apollo = inject(Apollo);

// Component input that might be null initially
public readonly bookId = input<string | null>();

protected readonly bookUpdateSubscription = this.apollo.signal.subscription({
subscription: BOOK_UPDATE_SUBSCRIPTION,
variables: () => {
const id = this.bookId();
return id ? { id } : null; // Return null if bookId is not available
}
});
}

Behavior when variables return null:

  • If the subscription hasn't started yet, it won't start until variables become non-null
  • If the subscription is already active, it will terminate (disconnect from the server and stop receiving updates)
  • When variables change from null to a non-null value, if the subscription is enabled then it will automatically execute

This pattern is useful for:

  • Waiting for required input parameters before starting a subscription
  • Conditionally subscribing to updates based on user selections
  • Preventing unnecessary subscriptions when dependencies are not ready

Lazy Subscriptions

In some cases, you may want to delay the execution of a subscription until a specific event occurs. This can be achieved by using the lazy option:

library/authors/authors.component.ts
import { Apollo } from '@apollo-orbit/angular';
import { NEW_AUTHOR_SUBSCRIPTION } from '../graphql/types';

@Component({
selector: 'app-authors',
template: `
<button (click)="toggleSubscription()">
{{ newAuthorSubscription.active() ? 'Stop' : 'Start' }} subscription
</button>

@if (newAuthorSubscription.data(); as data) {
<div class="alert-info">New author: {{ data.newAuthor.name }}</div>
}
`
})
export class AuthorsComponent {
private readonly apollo = inject(Apollo);

protected readonly newAuthorSubscription = this.apollo.signal.subscription({
subscription: NEW_AUTHOR_SUBSCRIPTION,
lazy: true, // Delay execution until explicitly called
onData: (data) => {
// Optional callback when new data arrives
console.log('New author:', data.newAuthor.name);
},
onError: (error) => {
// Optional callback for errors
console.error('Subscription error:', error);
},
onComplete: () => {
// Optional callback when subscription completes
console.log('Author subscription completed');
}
});

protected toggleSubscription(): void {
if (this.newAuthorSubscription.active()) {
this.newAuthorSubscription.terminate();
} else {
this.newAuthorSubscription.execute();
}
}
}

Setting lazy: true makes the subscription variables optional (even if required by the subscription), allowing you to pass them only when executing via the execute method.

Callbacks

signal.subscription supports optional callbacks for handling subscription events:

  • onData: Called when new data is received
  • onError: Called when an error occurs
  • onComplete: Called when the subscription completes

These callbacks are useful for side effects like logging, analytics, or triggering other actions.

Component Lifecycle

Similar to SignalQuery, SignalSubscription uses an effect internally to manage the subscription lifecycle. The subscription is automatically cleaned up when the component is destroyed, preventing memory leaks.

For non-lazy subscriptions, the subscription starts immediately when the component is created. For lazy subscriptions, you control when to start and stop the subscription using the execute() and terminate() methods.