Overview
Onwards with our next feature!
In this lesson, we will:
- Learn about GraphQL arguments and how to access them in a resolver function
- Learn how to use GraphQL variables in an operation
The mockup
Here's our next feature: the playlist page.
We'll most likely get to this page through a few ways: clicking on a specific playlist from the featured playlists page or maybe directly through a URL link.
However we get to this page, we'll need the playlist ID, which makes it a perfect use case for a GraphQL argument.
GraphQL arguments
An argument is a value you provide for a particular field in your query.
Resolvers can use a field's provided arguments to help determine how to populate the data for that field. Arguments can help retrieve specific objects, filter through a set of objects, or even transform the field's returned value. For example, a query that performs a search usually provides the user's search term as an argument.
A new entry point
Our schema evolves again! We're adding a new entry point.
Inside the Query
class, we'll add a new resolver called Playlist
, which returns a nullable Playlist
type. We're making this nullable because it's possible that the playlist we're looking for doesn't exist (for example, it may have been deleted).
public Playlist? Playlist(){}
This might get a little confusing, having a resolver function named the same as an object type, so what we can do is rename this resolver to GetPlaylist
instead. Behind the scenes, Hot Chocolate will remove the Get
prefix and map it to the same GraphQL field as if we had named it Playlist
.
public Playlist? GetPlaylist()
Note: Hot Chocolate will do the same for functions that end with Async
.
As a parameter inside the function, we'll define an id
of type string
, and add the [ID]
attribute to denote that this should be of type ID
in GraphQL.
Note that the id
parameter can be named anything, like playlistId
for example! We recommend collaborating with your team to decide on naming conventions. Using id
as the GraphQL argument name is a common convention.
public Playlist? GetPlaylist([ID] string id)
We'll also include the SpotifyService
in this resolver.
public Playlist? GetPlaylist([ID] string id, SpotifyService spotifyService) {
The data source method we'll need to call from the spotifyService
is GetPlaylistAsync
and it takes the id
as a parameter. We'll save the results in a variable called response
.
var response = spotifyService.GetPlaylistAsync(id);
The pattern here will be very similar to the FeaturedPlaylists
resolver. We'll make the function async
, await the response and return a Task<T>
type.
public async Task<Playlist?> GetPlaylist([ID] string id, SpotifyService spotifyService){var response = await spotifyService.GetPlaylistAsync(id);}
This resolver needs to return a Playlist
type, but response
is currently a SpotifyWeb.Playlist
type.
Jumping over to the Playlist.cs
file, let's add a new, additional constructor in the Playlist
class. We'll pass in a SpotifyWeb.Playlist
object and use its properties to initialize our own Playlist
's properties.
public Playlist(SpotifyWeb.Playlist obj){Id = obj.Id;Name = obj.Name;Description = obj.Description;}
(We'll tackle the playlist's tracks in the next lesson!)
Back in the resolver, let's finish off this familiar pattern by creating a Playlist
object from the response
then returning the result.
var playlist = new Playlist(response);return playlist;
Don't forget the description for the GetPlaylist
resolver!
[GraphQLDescription("Retrieves a specific playlist.")]
Let's save our changes and make sure our server is still running successfully with no problems.
Explorer time!
Time to see how our GraphQL schema has evolved with those changes! Let's jump back to Sandbox and create a new workspace.
In the Explorer page, navigating back to the root Query
type in the Documentation panel, we can see a new field: the playlist(...)
field.
Click on the + button beside "Fields" to add all three playlist fields to the operation.
query Playlist($playlistId: ID!) {playlist(id: $playlistId) {idnamedescription}}
We'll notice something new here: a dollar sign ($
) followed by the name playlistId
.
Variables
The $
symbol indicates a variable in GraphQL. The name after the $
symbol is the name of our variable, which we can use throughout the query. After the colon is the variable's type, which must match the type of the argument we'll use it for.
Variables are great—they let us pass argument values dynamically from the client-side so we don't have to hardcode values into our query. We'll use them every time we create a query with arguments.
In our case, we have a variable called playlistId
that the Explorer set up for us down in the Variables section. Right now, it's set to null
.
If we try to run the query now, we'll still get a JSON object back, but this time with an errors
key, instead of data
:
{"errors": [{"message": "Variable `playlistId` is required.","locations": [{"line": 1,"column": 16}],"extensions": {"code": "HC0018","variable": "playlistId"}}]}
This lets us know that we can't leave the playlistId
as null
, because the schema specifically defines the id
argument (where we're using the playlistId
variable) as a non-nullable type!
Let's go ahead and update the null
value to a playlist ID we know exists from the featuredPlaylists
query.
{"playlistId": "6Fl8d6KF0O4V5kFdbzalfW"}
Lastly, we'll rename the operation to be a bit more descriptive — like GetPlaylistDetails
.
query GetPlaylistDetails($playlistId: ID!) {playlist(id: $playlistId) {idnamedescription}}
Run the query to get the details of the Sweet Beats & Eats
playlist!
Practice
Playlist
type returned from the GetPlaylist
resolver marked as nullable?Key takeaways
- Arguments are values provided for a particular field in a GraphQL query. Resolvers use field arguments to determine how to populate data for that field.
- The
$
symbol indicates a variable in GraphQL. The name after the$
symbol is the name of our variable, which we can use throughout the query. After the colon is the variable's type, which must match the type of the argument we'll use it for.
Up next
We hear you, you're ready for some jams! We'll add the playlist's tracks in the next lesson.
Share your questions and comments about this lesson
This course is currently in
You'll need a GitHub account to post below. Don't have one? Post in our Odyssey forum instead.