# WatchQuery
The WatchQuery is a lot like a traditional Query. However, the WatchQuery is an async process that can be used to fire multiple queries. It is great for paginated views or for data that will change over time.
On top of this, the WatchQuery has the option to subscribe to model changes from the backend.
Basic subscriptions are defined with the @subscribe
-directive.
More advanced subscriptions are created with the Subscription-operation.
# Initializing a new WatchQuery
A WatchQuery is initialized through the Buoy-service.
export class AppComponent {
public myMovie: Query;
constructor(
private buoy: Buoy
) {
this.myMovie = this.buoy.watchQuery(
// Query
gql `
query Movie($id: Int!) {
movie(id: $id) {
title
poster
}
}
`,
// Variables
{
id: 1
},
// Options
{
scope: 'movie'
}
);
}
}
The myMovie
-variable will contain a WatchQuery-object. To access the data returned from the GraphQL-server, use the data
-parameter (see variables).
# Using the data in your template
The scoped response from the GraphQL-server is available in the data
-variable.
<div *ngIf="!myMovie.loading">
<h1>{{ myMovie.data?.title }}</h1>
<img *ngIf="myMovie.data?.poster !== null"
[src]="myMovie.data?.poster" />
</div>
<div *ngIf="myMovie.loading">
Loading...
</div>
# Variables
The WatchQuery-object has following variables available:
Parameter | Type | Explanation |
---|---|---|
data | any | Contains the scoped response from the GraphQL-server. |
pagination | any | Pagination-details: currentPage, lastPage, perPage, etc. |
loading | bool | Whether or not, the query is currently loading. |
# Methods
# nextPage
Go to the next page. Will only change page, if not on last page.
Parameters
Parameter | Type | Explanation |
---|---|---|
refetch | boolean | (Optional / default: true) Refetch the query after page changed? |
paginator | string | (Optional) The paginator. Only required if using multiple paginators. |
# prevPage
Go to the previous page. Will only change page, if not on first page.
Parameters
Parameter | Type | Explanation |
---|---|---|
refetch | boolean | (Optional / default: true) Refetch the query after page changed? |
paginator | string | Optional: The paginator. Only required if using multiple paginators. |
# setPage
Go to a specific page. Will only change page if the page is available.
Parameters
Parameter | Type | Explanation |
---|---|---|
page | number | The desired page. |
refetch | boolean | (Optional / default: true) Refetch the query after page changed? |
paginator | string | Optional: The paginator. Only required if using multiple paginators. |
# setLimit
Go to a specific page. Will only change page if the page is available.
Parameters
Parameter | Type | Explanation |
---|---|---|
limit | number | The desired limit. |
refetch | boolean | (Optional / default: true) Refetch the query after limit changed? |
paginator | string | Optional: The paginator. Only required if using multiple paginators. |
# refetch
Runs the query with the current options and variables.
Parameters
none
# setVariable
Set a variable after the query has been initialized. You must use refetch()
in order to see the changes.
Parameters
Parameter | Type | Explanation |
---|---|---|
variable | string | The name of the variable. |
value | any | The value of the variable. |
# unsetVariable
Remove a variable from the query. You must use refetch()
in order to see the changes.
Parameters
Parameter | Type | Explanation |
---|---|---|
variable | string | The name of the variable. |
# Options
Options are added as the third parameter on the buoy.watchQuery()
-method.
# pagination
The pagination-option can be used in a few different ways.
Buoy automatically adds the necessary variables, variable values and attributes for pagination to the query. However, you may still want to add the variables and attributes to your query in order for your code completion to work properly (depending on your IDE).
TIP
If you need to set the initial pagination values for page and limit, simply add them as parameters to the query. However, once initialized, you must use the pagination methods to change page and limit.
Basic pagination
With basic pagination, you simply enter a scope of the paginator.
Example:
// Options
{
pagination: 'movies'
}
query Movies ($limit: Int!, $page: Int!) {
movies(first: $limit, page: $page) {
data {
id
title
}
}
}
In this example the variables will be: limit
, page
.
Multiple paginators
With this method, an array of scopes are defined.
Example:
// Variables
{
actorId: 1 // This variable must be defined, since it is not related to pagination.
},
// Options
{
pagination: [
'movies',
'actor.roles'
]
}
query MyQuery (
# This variable must be defined, since it is not related to pagination.
$actorId: Int!,
# It is optional to add pagination-variables
$moviesLimit: Int!,
$moviesPage: Int!,
$actorRolesLimit: Int!,
$actorRolesPage: Int!
) {
movies(first: $moviesLimit, page: $moviesPage) {
data {
id
title
}
}
actor(id: $actorId) {
roles(first: $actorRolesLimit, page: $actorRolesPage) {
data {
character
}
}
}
}
In this example the variables will be: moviesLimit
, moviesPage
, actorRolesLimit
and actorRolesPage
.
Multiple paginators with custom paginator-type
Use this type of pagination, if you need to query something with a paginatorType that differs from the default.
Example:
// Variables
{
actorId: 1 // This variable must be defined, since it is not related to pagination.
},
// Options
{
pagination: {
'movies': 'paginator',
'actor.roles': 'connection'
}
}
query MyQuery (
# This variable must be defined, since it is not related to pagination.
$actorId: Int!,
# It is optional to add pagination-variables
$moviesLimit: Int!,
$moviesPage: Int!,
$actorRolesLimit: Int!,
$actorRolesPage: ID! # A paginator of type "connection" use ID! for page
) {
movies(first: $moviesLimit, page: $moviesPage) {
data {
id
title
}
}
actor(id: $actorId) {
roles(first: $actorRolesLimit, after: $actorRolesPage) {
edges {
character
}
}
}
}
# scope
The scope will change the root of the data returned by the GraphQL-server.
The server will often return something like this:
{
"movies": {
"data": [
{ "title": "Movie 1" },
{ "title": "Movie 2" }
]
}
}
With the scope movies.data
, you can skip the two first levels, and receive:
[
{ "title": "Movie 1" },
{ "title": "Movie 2" }
]
The scope should generally be the name of the first node in your query followed by .data
, if your node is a paginator.
# router
This enables Router R/W, which automatically handles the necessary query params for pagination and custom variables in the query. Enabling this, will allow the user to share a link to the page and have it load the exact same results.
Please refer to Router R/W for more information.
// Options
{
router: {
route: ActiveRoute,
router: Router
}
}
# Callbacks
The callbacks are also added as options on a WatchQuery.
# onInitialized
Is fired once the WatchQuery has been initialized.
Parameters
Parameter | Type | Explanation |
---|---|---|
id | number | Buoy operation ID |
# onChange
Is fired when the data changes.
Parameters
Parameter | Type | Explanation |
---|---|---|
id | number | Buoy operation ID |
data | any | Scoped data. |
# onLoadingStart
Is fired when loading
is set to true
.
Parameters
Parameter | Type | Explanation |
---|---|---|
id | number | Buoy operation ID |
# onLoadingFinished
Is fired when loading
is set to false
.
Parameters
Parameter | Type | Explanation |
---|---|---|
id | number | Buoy operation ID |
# Directives
# @subscribe
The subscribe-directive can be applied to the second level of queries, for example:
query {
# Applied to a single model
note(id: 123) @subscribe {
id
name
}
# Applied to a paginated list of models
notes(first: 25, page: 1) @subscribe {
data {
id
name
}
}
}
Defition:
enum EventType {
CREATE
UPDATE
DELETE
}
directive @subscribe (
"Argument to send to the subscription. Will default to 'id'."
argument: String
"Arguments to send to the subscription. Will default to 'id'."
arguments: [String!]
"Only subscribe the defined event type."
event: EventType
"Only subscribe to defined event types."
events: [EventType!]
) on FIELD_DEFINITION
# @skipSubscription (wip)
This directive can be used to skip individual fields based on the event type.
WARNING
This directive requires the GraphQL server to implement the Fairway-spec (opens new window).
In this example, the author is to only be included in CREATE-events:
query {
notes(first: 25, page: 1) @subscribe {
data {
id
name
# Only include the author in CREATE-events
author @skipSubscription(events: [UPDATE, DELETE]) {
id
name
}
# Exclude from all subscription-events
otherField @skipSubscription
}
}
}
Defition:
enum EventType {
CREATE
UPDATE
DELETE
}
directive @skipSubscription (
"Skip the field for defined event types"
events: [EventType!]
) on FIELD_DEFINITION