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<TData, TVariables>
): 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 | nullThe operation's variables, as a function or signal re-read whenever its reactive dependencies change.

Returning null terminates the operation until it returns a non-null value 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.
variablesWritableSignal<TVariables | null | undefined>A writable signal that represents the current subscription variables.
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';

@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​

Variables are given to signal.subscription as a function or signal, never as a plain object, for the reason set out in signal.query. When its reactive dependencies change, SignalSubscription updates the variables and restarts the subscription.

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

@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 are null, or 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';

@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';

@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 first internal effect starts the subscription once its variables are available. For lazy subscriptions, execute() starts it explicitly.

enabled() allows automatic restarts on variable changes; active() reports a connection. Completion clears active() and loading() but retains the result and leaves enabled() true. terminate() disables restarts until execute(); null variables pause without disabling them.