@@ -14,7 +14,7 @@ include ../_util-fns
14
14
15
15
<a id =" toc" ></a >
16
16
:marked
17
- ## Table of contents
17
+ ## Contents
18
18
19
19
- [What is GraphQL?](#what-is-graphql)
20
20
@@ -106,12 +106,8 @@ a#http-heroes
106
106
1. A dependency between the service and all of the components that use it
107
107
make the component no longer reusable. If you change something in the service,
108
108
it might break other components that use that service.
109
- 2. There is a main, complex point to handle batching, caching, and join logic.
110
-
111
- .alert.is-important
112
- :marked
113
- Uri: Could you add a sentence to #2 above explaining why this
114
- is a bad idea like you did in #1?
109
+ 2. There is a main, complex point to handle batching, caching, and join logic.
110
+ Because the logic is shared between components, the potential of things breaking increases.
115
111
116
112
:marked
117
113
#### Fetching data at the parent component and passing it down the component tree
@@ -133,55 +129,37 @@ a#http-heroes
133
129
134
130
135
131
:marked
136
- Here, the data dependency is inside or next to the component and when the data dependency changes,
137
- the component is the only thing that was changed—no service or parent component were harmed in the making of this component.
138
-
139
- .alert.is-important
140
- :marked
141
- Uri: The above sentence could use some editing, but as I started, I wasn't sure I was
142
- saying the right thing. Does this work?
143
-
144
- "Here, the data dependency is inside the component. Alternatively, it could go next to
145
- the component. When the data dependency changes, only the component need change.
146
- You don't have to touch any services or parent components."
147
-
148
- What do you mean by "next to it" exactly? Could we say that explicitly? I also like the
149
- tone of "were harmed in the making of..." but since I have to change to the present tense
150
- the reference isn't as smooth. If you can work it in, I'm fully supportive. I thought
151
- it was a good way to make the point.
132
+ Here, the data dependency is inside the component. The query reflects just
133
+ what the single component needs and is included as part of the
134
+ component or a wrapper component. That means that when the
135
+ data dependency changes, the component is the only thing
136
+ impacted. You don't have to touch any services or parent components.
152
137
153
138
:marked
154
- Now, a single component contains all the data dependency changes.
155
-
156
- .alert.is-important
157
- :marked
158
- Uri: Could you explain the `watchQuery` code snippet below? Just a couple of sentences would
159
- work.
139
+ Now, a single component contains all of its own data dependency changes.
160
140
161
141
:marked
162
- (Explanation could go here followed by the fact that it simplifies adding `age`....)
163
- For example, adding an `age` field to the app is simple:
142
+ The `watchQuery` function tells the Apollo Client what data
143
+ this component needs. The Apollo Client then returns the
144
+ necessary data to the component as an Observable.
145
+ For example, adding an `age` field to the app is
146
+ simple because you only change the component itself:
164
147
165
148
+ makeExample('heroes-graphql/ts/src/app/hero-detail.component.1.ts' ,'graphql-query-new-field' ,'Adding an `age` field to the component' )
166
149
+ makeExample('heroes-graphql/ts/src/app/hero-detail.component.1.html' ,'template-new-field' ,'Adding an `age` field to the template' )
167
150
168
- .alert.is-important
169
- :marked
170
- Uri: This section where you show the solution is where you're selling the idea -
171
- where you're showing the reader why they should continue in this doc. Could you
172
- make that point here in a sentence or two? I'd try but don't quite understand
173
- it yet.
174
-
151
+ :marked
152
+ So far, you've seen how to fetch data for a component while
153
+ keeping the component isolated from the rest of the app.
154
+ That solves the most time-consuming and bug provoking code
155
+ that one usually writes in order to fetch data from the server.
156
+ You can also use GraphQL to improve efficiency.
175
157
176
158
:marked
177
159
### Network Performance
178
160
179
- The [Heroes HTTP example](#http-heroes) calls `getHeroes` to fetch all heroes and their information.
180
-
181
- .alert.is-important
182
- :marked
183
- Uri: Not sure I linked the above to the right spot. If so, the text in both places should
184
- read the same. It's linking to "Using a Service" because that's where I saw `getHeroes`.
161
+ The [Tour of Heroes HTTP guide](latest/tutorial/toh-pt6.html)
162
+ calls `getHeroes` to fetch all heroes and their information.
185
163
186
164
:marked
187
165
That might work for simple cases but the problem here is that `getHeroes` might fetch
@@ -191,16 +169,27 @@ a#http-heroes
191
169
server, you might break the components that use that endpoint.
192
170
193
171
The other approach would be to call `getHeroes`, get the ids of the heroes and call `getHero` for each id.
194
- That might result in multiple requests to the server for one single render of the page.
172
+ That might result in _multiple requests to the server_ for one single render of the page.
195
173
196
- With a REST API, you would always have to choose between those two options and the problems of each option.
174
+ With a REST API, you _always have to choose between those two options_ and
175
+ their respective problems.
197
176
198
- With GraphQL, you just specify the dependency of each component and a GraphQL client library, like [Apollo-Client](http://dev.apollodata.com/),
199
- to merge those into one single network request. GraphQL sends back the information
177
+ :marked
178
+ With GraphQL, you just specify the dependency of each component and a
179
+ GraphQL client library, like the [Apollo Client](http://dev.apollodata.com/),
180
+ to merge those into **one single network request**. GraphQL sends back the information
200
181
in a single response, with exactly the information you need—no more, no
201
- less—and no need to do complex joins or wait for responses.
182
+ less—in exactly the structure and shape you want the data to be with
183
+ no need to do complex joins or wait for responses.
202
184
203
- ### Typed API and tooling
185
+ .l-sub-section
186
+ :marked
187
+ You can work with the Apollo Client
188
+ while still keep your existing REST services in your Angular app
189
+ and migrate gradually from them.
190
+
191
+ :marked
192
+ ### Typed API, tooling and auto documentation
204
193
205
194
Just as TypeScript provides tooling to increase productivity and best practices,
206
195
GraphQL provides a similar solution for working with APIs.
@@ -209,29 +198,20 @@ a#http-heroes
209
198
can change without notice.
210
199
211
200
With GraphQL, the schema is typed and shared between the client
212
- and the server so you can get the same benefits when working with
213
- the network—validation and autocompletion inside the IDE at development time.
214
-
215
- .alert.is-important
216
- :marked
217
- Uri: I don't understand this last sentence above. I get lost at "working with the
218
- network...". What do you mean exactly? I realize it might just be beyond my experience,
219
- but could you explain it to a mid-level dev?
220
-
201
+ and the server. As a result, just as with Angular and TypeScript,
202
+ you get the same development experience when calling calling a remote
203
+ API—validation and autocompletion inside the IDE at development time.
221
204
222
205
.l-main-section
223
206
<a id =" how-to" ></a >
224
207
:marked
225
208
## How to use GraphQL in an Angular app
226
209
227
210
This guide uses [Apollo-Client](http://dev.apollodata.com/) as the GraphQL client for Angular.
228
- Apollo helps you query GraphQL and provides X, Y, and Z.
229
-
230
- .alert.is-important
231
- :marked
232
- Uri: Could you specify those benefits where I wrote "X, Y, and Z"? I would but am still
233
- trying to wrap my mind around it. I think this is talking about what you
234
- touched on in the solution section, but I wasn't clear on all the benefits there.
211
+ Apollo helps you query GraphQL and provides a caching layer
212
+ with common features you need for querying a server such as
213
+ caching, mutations, optimistic UI, real-time subscriptions,
214
+ pagination, server-side rendering, and prefetching.
235
215
236
216
.l-sub-section
237
217
:marked
@@ -251,37 +231,22 @@ code-example(language="sh" class="code-shell").
251
231
Next, initialize the client by creating a new file called `client.ts` and
252
232
pasting in the following code:
253
233
254
- .alert.is-important
255
- :marked
256
- Uri: Now that we are telling people to copy the code into their project, we should
257
- use the blue headers on the code snippets to name the file and show where it is,
258
- such as `app/client.ts`, like this:
259
-
260
234
+ makeExample('heroes-graphql/ts/src/app/client.1.ts' , '' , 'app/client.ts' )
261
235
:marked
262
- This is the default initialization of Apollo and is referred to as the `/graphql` endpoint.
236
+ This is the default initialization of Apollo and calls the `/graphql` endpoint.
263
237
First, import `ApolloClient`, create a constant for the new instance of the client,
264
238
and export it so that it is available to the app.
265
239
266
-
267
- .alert.is-important
240
+ .l-sub-section
268
241
:marked
269
- Uri: I'm a little confused here. Is this (below) a necessary step? Can we start by showing them
270
- the above code and then telling them to paste in this snippet so they don't have to
271
- immediately paste over something that they just put in their project?
272
- Do we need to change the endpoint? If both snippets are needed,
273
- let's explain why. Both are fine to have if we can lead the reader through why.
274
-
275
- If this is more of a handy piece of info to simply have in one's repertoire, we could
276
- put this in an aside or a note, so people don't think it's a step they
277
- have to follow for this guide.
278
-
279
- :marked
280
- To change the [settings](http://dev.apollodata.com/core/apollo-client-api.html#ApolloClient\.constructor)
281
- of `ApolloClient`, call its constructor with different parameters.
282
- For example, you can alter the endpoint by importing `createNetworkInterface` and configuring the
283
- `networkInterface` property of `ApolloClient` to
284
- use a URI:
242
+ ### To use a different URI for the Apollo Client
243
+ You don't need the following code snippet to work through this cookbook,
244
+ but it's good to know how to configure the client to use a URI.
245
+ To change the [settings](http://dev.apollodata.com/core/apollo-client-api.html#ApolloClient\.constructor)
246
+ of `ApolloClient`, call its constructor with different parameters.
247
+ You can alter the endpoint by importing `createNetworkInterface` and configuring the
248
+ `networkInterface` property of `ApolloClient` to
249
+ use a URI:
285
250
286
251
+ makeExample('heroes-graphql/ts/src/app/client.2.ts' , 'network-initialization' , 'app/client.ts' )
287
252
.l-sub-section
@@ -291,96 +256,55 @@ code-example(language="sh" class="code-shell").
291
256
The appendix shows you how to run a GraphQL server in-memory
292
257
on the client, which is helpful for testing.
293
258
294
- .alert.is-important
295
- :marked
296
- Uri: Two things.
297
-
298
- 1. For the above, you had that it was a good way to move your app
299
- gradually to GraphQL. Could you explain why? We can put that in there,
300
- I just couldn't figure out how to work that phrase into a sentence.
301
-
302
- 2. If the project in this guide requires the server, we should consider
303
- moving it up, taking it out of an appendix. What do you think?
304
-
305
259
:marked
306
260
After initializing the Apollo client, import the `ApolloModule`
307
261
into the app's root module:
308
262
+ makeExample('heroes-graphql/ts/src/app/app.module.ts' , 'import-apollo' , 'app.module.ts (excerpt)' )
309
263
310
264
:marked
311
- Next, add `ApolloModule.withClient(getClient)` to the `@NgModule` imports array.
265
+ Next, add `ApolloModule.forRoot(getClient)` to the `@NgModule` imports array. This
266
+ is an initialization function that accepts the Apollo configuration
267
+ you created earlier as an argument and creates a new Apollo instance for the app.
312
268
313
- .alert.is-important
314
- :marked
315
- Uri: Could you explain `ApolloModule.withClient(getClient)`?
316
269
+ makeExample('heroes-graphql/ts/src/app/app.module.ts' , 'apollo-ngmodule' , 'app.module.ts (excerpt)' )
317
270
318
271
.l-main-section
319
272
<a id =" querying" ></a >
320
273
:marked
321
274
## Performing a query
322
275
323
- With GraphQL you always query a server that has a schema representing the data it exposes.
324
- A schema is or serves as a ...
325
-
326
- The server for this guide is based on the [Tour of Heroes](link here please ).
276
+ With GraphQL you query a schema, which is organized into types and fields,
277
+ that represents the data you can query.
278
+
279
+ The server for this guide is based on the [Tour of Heroes](ts/latest/tutorial/ ).
327
280
Copy the schema that follows into a file named `in-memory-graphql.ts` in the `app` directory:
328
281
329
- .alert.is-important
330
- :marked
331
- Uri:
332
-
333
- 1. Could you define schema right after you first mention it? I've started the
334
- sentence for you above so you can see what I have in mind. Feel free to
335
- change/move it though.
336
-
337
- 2. Could you link the above "Tour of Heroes" to the place you're referencing?
338
-
339
- 3. Could you add a sentence or two here explaining what's happening in the schema?
340
- The comments are good, but we also want to have a continuous thread in the prose
341
- voice that carries us through.
342
-
343
- 4. In explaining the schema, just a sentence or two about what the different parts
344
- are would be helpful with a little about the syntax. For example, I think I
345
- can declare certain types - what are they and what's that curious syntax? We want
346
- to tell them declaratively, rather than leaving them to their own assumptions.
347
-
348
- 4. Please be sure to remove "we", "let's", "our/s" and "us"
349
- from comments as well as the jade. I've been removing them here, but it's
350
- possible that I have missed some. I haven't gone into the `_example` files.
282
+ :marked
283
+ The schema begins with data types and fields followed by the specific queries
284
+ you can perform on the data. These are in turn followed by
285
+ mutations, which are _actions_ that you
286
+ can call on the server, similar to a POST request in REST.
351
287
352
288
+ makeExample('heroes-graphql/ts/src/app/in-memory-graphql.ts' , 'graphql-schema' , 'app/in-memory-graphql.ts' )
353
289
354
290
:marked
355
- To use the schema, start by importing `Apollo` into `heroes.component.ts`,
291
+ To start querying data, begin by importing `Apollo` into `heroes.component.ts`,
356
292
and injecting it into the constructor:
357
293
+ makeExample('heroes-graphql/ts/src/app/heroes.component.ts' , 'import-apollo' , 'heroes.component.ts (excerpt)' )
358
294
+ makeExample('heroes-graphql/ts/src/app/heroes.component.ts' , 'inject-apollo' , 'heroes.component.ts (excerpt)' )
359
295
:marked
360
296
Now that the schema is available to the app, the next step is querying it.
361
297
In the component, import `gql` from the `graphql-tag` library.
362
- The `gql` function parses regular string literals as GraphQL.
363
-
364
- .alert.is-important
365
- :marked
366
- Uri: Could you explain in just a sentence or two what it means when
367
- we parse string literals as GraphQL?
298
+ The `gql` function turns your query string to something `Apollo`
299
+ can accept and understand.
368
300
369
301
+ makeExample('heroes-graphql/ts/src/app/heroes.component.ts' , 'import-graphql-tag' , 'heroes.component.ts' )
370
302
371
303
:marked
372
- To query data with the Apollo Client, pass `Apollo` a query in the GraphQL
373
- query syntax. In this example, ......
374
- .alert.is-important
375
- :marked
376
- Uri: Could you give a brief explanation of what's happening in the below
377
- code snippet? Please touch on if we are putting it in the component (I think so),
378
- and what each section means. This is a really important part of this tutorial and
379
- people will be very interested in the unique syntax. Brief is fine, since we don't
380
- want to go too far into it, but we should exaplain on this page what each line means.
381
- This might be 2 or 3 short paragraphs. Please also touch on the use of observables.
382
- You can say something to the effect that we are using observables here because x and
383
- they can tell that because of `subscribe`. You could include a link to ....(I'm finding the right link...).
304
+ To query data with the Apollo Client, pass a GraphQL query with the
305
+ data and structure that you want to the `Apollo` `watchQuery` function.
306
+ The `Apollo` ` watchQuery` function will return the data from the
307
+ server in the form of an Observable.
384
308
385
309
+ makeExample('heroes-graphql/ts/src/app/heroes.component.ts' , 'query-heroes' , 'heroes.component.ts' )
386
310
@@ -391,15 +315,9 @@ code-example(language="sh" class="code-shell").
391
315
Next, update the template so it will display the results of the query.
392
316
+ makeExample('heroes-graphql/ts/src/app/heroes.component.1.html' , 'render-heroes' , 'heroes.component.html' )
393
317
394
- .alert.is-important
395
- :marked
396
- Uri:
397
-
398
- 1. Since we haven't talked about the template yet, do you think we should show
399
- the whole thing with some comments making this section (above) stand out?
400
-
401
- 2. Do the results show up at this point? If so, maybe we should mention that. If not,
402
- we should say so.
318
+ :marked
319
+ At this point, if you have a running [GraphQL server](#server), the browser displays the
320
+ fetched data.
403
321
404
322
.l-main-section
405
323
<a id =" mutation" ></a >
0 commit comments