Skip to content
This repository was archived by the owner on Dec 4, 2017. It is now read-only.

Commit 98936f3

Browse files
committed
docs(cookbook/graphql): Fix for @kapunahelewong review
1 parent caddf91 commit 98936f3

File tree

5 files changed

+183
-14
lines changed

5 files changed

+183
-14
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
// #docregion
2+
import { Component, OnInit } from '@angular/core';
3+
import { Router } from '@angular/router';
4+
5+
// #docregion import-apollo
6+
import { Apollo } from 'apollo-angular';
7+
// #enddocregion import-apollo
8+
// #docregion import-graphql-tag
9+
import gql from 'graphql-tag';
10+
// #enddocregion import-graphql-tag
11+
import { ApolloQueryResult } from 'apollo-client';
12+
import { Hero } from './hero';
13+
14+
@Component({
15+
moduleId: module.id,
16+
selector: 'my-heroes',
17+
templateUrl: './heroes.component.html',
18+
styleUrls: [ './heroes.component.css' ]
19+
})
20+
export class HeroesComponent implements OnInit {
21+
// #docregion this-heroes
22+
heroes: Hero[];
23+
selectedHero: Hero;
24+
// #enddocregion this-heroes
25+
26+
// #docregion inject-apollo
27+
constructor(
28+
private apollo: Apollo,
29+
private router: Router) { }
30+
// #enddocregion inject-apollo
31+
32+
// #docregion query-heroes
33+
getHeroes(): void {
34+
this.apollo.watchQuery({
35+
query: gql`
36+
query allHeroes {
37+
heroes {
38+
id
39+
name
40+
}
41+
}
42+
`,
43+
forceFetch: true
44+
}).subscribe((queryResult: ApolloQueryResult<{ heroes: Hero[] }>) => {
45+
this.heroes = queryResult.data.heroes;
46+
});
47+
// #enddocregion query-heroes
48+
}
49+
50+
// #docregion add
51+
add(name: string): void {
52+
name = name.trim();
53+
if (!name) { return; }
54+
55+
// #docregion add-mutation
56+
this.apollo.mutate({
57+
mutation: gql`
58+
mutation addHero($heroName: String!) {
59+
addHero(heroName: $heroName) {
60+
id
61+
name
62+
}
63+
}
64+
`,
65+
variables: {
66+
heroName: name
67+
}
68+
}).subscribe((mutationResult: ApolloQueryResult<{ addHero: Hero }>) => {
69+
this.heroes.push({
70+
// #docregion access-mutation-result
71+
id: mutationResult.data.addHero.id,
72+
name: mutationResult.data.addHero.name
73+
// #enddocregion access-mutation-result
74+
});
75+
});
76+
// #enddocregion add-mutation
77+
}
78+
// #enddocregion add
79+
80+
// #docregion delete
81+
delete(hero: Hero): void {
82+
83+
this.apollo.mutate({
84+
mutation: gql`
85+
mutation deleteHero($id: Int!) {
86+
deleteHero(id: $id) {
87+
id
88+
name
89+
}
90+
}
91+
`,
92+
variables: {
93+
id: hero.id
94+
}
95+
}).subscribe((mutationResult: ApolloQueryResult<{ deleteHero: Hero }>) => {
96+
this.heroes = this.heroes.filter(h => h !== hero);
97+
if (this.selectedHero === hero) { this.selectedHero = null; }
98+
});
99+
}
100+
// #enddocregion delete
101+
102+
ngOnInit(): void {
103+
this.getHeroes();
104+
}
105+
106+
onSelect(hero: Hero): void {
107+
this.selectedHero = hero;
108+
}
109+
110+
gotoDetail(): void {
111+
this.router.navigate(['/detail', this.selectedHero.id]);
112+
}
113+
}

public/docs/_examples/heroes-graphql/ts/src/app/heroes.component.ts

+2
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,10 @@ export class HeroesComponent implements OnInit {
6767
}
6868
}).subscribe((mutationResult: ApolloQueryResult<{ addHero: Hero }>) => {
6969
this.heroes.push({
70+
// #docregion access-mutation-result
7071
id: mutationResult.data.addHero.id,
7172
name: mutationResult.data.addHero.name
73+
// #enddocregion access-mutation-result
7274
});
7375
this.selectedHero = null;
7476
});

public/docs/_examples/heroes-graphql/ts/src/app/in-memory-graphql.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,13 @@ import { execute } from 'graphql';
1010
// #enddocregion import-graphql
1111
// #docregion graphql-schema
1212
const typeDefinitions = `
13+
# the model
1314
type Hero {
1415
id: Int!
1516
name: String!
1617
}
1718
18-
# the schema allows the following query:
19+
# the schema allows the following queries:
1920
type Query {
2021
heroes(search: String): [Hero]
2122
@@ -38,8 +39,8 @@ type Mutation {
3839
): Hero
3940
}
4041
41-
# we need to tell the server which types represent the root query
42-
# and root mutation types. We call them RootQuery and RootMutation by convention.
42+
# you need to tell the server which types represent the root query
43+
# and root mutation types. you call them RootQuery and RootMutation by convention.
4344
schema {
4445
query: Query
4546
mutation: Mutation

public/docs/ts/latest/cookbook/graphql.jade

+64-11
Original file line numberDiff line numberDiff line change
@@ -376,9 +376,29 @@ code-example(language="json").
376376
:marked
377377
Now for the fun part. Inside of the `add()` function, add an `addHero` mutation
378378
using the `apollo.mutate` function as follows:
379-
+makeExample('heroes-graphql/ts/src/app/heroes.component.ts', 'add-mutation', 'heroes.component.ts')
379+
+makeExample('heroes-graphql/ts/src/app/heroes.component.2.ts', 'add-mutation', 'heroes.component.ts')
380380
:marked
381381
The mutation requires and variable and we pass it to the `mutate` function through the `variables` param.
382+
383+
As mentioned above, with GraphQL mutations, you specify the result you want to get back from the server.
384+
385+
Apollo's `mutate` function returns the result as an Observable.
386+
The Observable returns a `mutationResult` variable that is structured
387+
like the `ApolloQueryResult` Typescript Type, where the generic `T` type is a `Hero` type:
388+
code-example(language="json").
389+
type ApolloQueryResult&lt;T> = {
390+
data: T;
391+
loading: boolean;
392+
networkStatus: NetworkStatus;
393+
};
394+
:marked
395+
and that's also how you reference that result variable in Typescript.
396+
So in order the get the actual hero data being returned, you access those values like so:
397+
+makeExample('heroes-graphql/ts/src/app/heroes.component.ts', 'access-mutation-result', 'heroes.component.ts')
398+
:marked
399+
and then push them into the `heroes` array.
400+
401+
382402
.alert.is-important
383403
:marked
384404
Uri: Could you explain this above segment section by section?
@@ -393,11 +413,17 @@ code-example(language="json").
393413
of what an observable is...I see we are pushing the `id` and `name` but
394414
don't quite understand how/when. The subscribe syntax loses me. Lastly,
395415
I don't know why we are setting the `selectedHero` to `null`.
416+
:Kapunahele - changed above
396417

397418
:marked
398419
Just like a query, the mutate function returns an Observable you can subscribe to
399420
that handles the data you request.
400421

422+
At this point, your heroes existing heroes app can also add a hero:
423+
figure.image-display
424+
img(src='/resources/images/cookbooks/heroes-graphql/heroes- graphql-mutation.gif' alt="Heroes GraphQL Mutation")
425+
426+
401427
.alert.is-important
402428
:marked
403429
Uri: Let's say something here about how we can now add a hero. Can the
@@ -407,6 +433,7 @@ code-example(language="json").
407433
Imagine the reader coming to this page and giving it a cursory scroll
408434
to see how long it is in deciding whether or not to work through it.
409435
A gif (especially) or screenshot could help them decide to do it.
436+
::Kapunahele - great point. added.
410437

411438
.l-main-section
412439
<a id="resources"></a>
@@ -436,13 +463,16 @@ code-example(language="json").
436463
Running the server in the browser helps you start using
437464
GraphQL on your frontend without having a GraphQL backend.
438465
If you don't have the option of running GraphQL on the server,
439-
this method makes it easier to handle multiple REST
440-
requests and join logic on the client.
466+
this method makes it possible to still use GraphQL in your app with the
467+
benefits for not needing to sync multiple REST requests and join logic
468+
on the client.
441469

442470
.alert.is-important
443471
:marked
444472
Uri: Can you tell me why it makes it easier? We should say
445473
"...logic on the client because..."
474+
:Kapunahele - changed above
475+
446476

447477
.l-sub-section
448478
:marked
@@ -451,14 +481,15 @@ code-example(language="json").
451481
it is almost identical to the local server in this appendix.
452482
Everything you learn here applies to writing an actual GraphQL backend server.
453483

454-
Additionally, there are a few GraphQL based backend-as-a-service platforms available,
455-
such as Firebase, but they are based on the GraphQL API. For help on getting
456-
up and running, see [Scaphold](https://www.scaphold.io/) and [Graphcool](https://www.graph.cool/).
484+
Additionally, there are a few GraphQL backend-as-a-service platforms available,
485+
similar to Firebase, but based on the GraphQL API spec.
486+
For help on getting up and running, see [Scaphold](https://www.scaphold.io/) and [Graphcool](https://www.graph.cool/).
457487

458488
.alert.is-important
459489
:marked
460490
Uri: Can you explain why the GraphQL API makes using things like Firebase different?
461491
There's a "but" in that sentence, but I don't know what it implies.
492+
:Kapunahele - the word `but` was wrong. fixed and edited a bit
462493

463494
:marked
464495
In order to create a GraphQL schema, you need the `graphql-tools` library.
@@ -477,7 +508,7 @@ code-example(language="sh" class="code-shell").
477508
.alert.is-important
478509
:marked
479510
Uri: Could you change the use of "we" in the above comments to "you" or the imperative (command without
480-
"you")?
511+
"you")? :Kapunahele - done.
481512
.l-sub-section
482513
:marked
483514
While the schema includes the major points covered in this cookbook,
@@ -502,13 +533,16 @@ code-example(language="sh" class="code-shell").
502533
:marked
503534
You may have noticed some functions from `lodash` such as `lodashFind()` so don't
504535
forget to install them from npm and import them:
536+
code-example(language="sh" class="code-shell").
537+
npm install lodash --save
505538
+makeExample('heroes-graphql/ts/src/app/in-memory-graphql.ts', 'import-lodash', 'in-memory-graphql.ts (imports)')
506539

507540
.alert.is-important
508541
:marked
509542
Uri: What is the npm install command for the lodash functions?
510543
Do we install the whole lodash library or just the functions?
511544
(I've never used lodash before).
545+
:Kapunahele - fixed. for ease of use I've installed all of lodash
512546

513547

514548
:marked
@@ -517,7 +551,8 @@ code-example(language="sh" class="code-shell").
517551

518552
This mechanism makes writing simple GraphQL servers straightforward&mdash;you simply
519553
resolve a specific type of data.
520-
This removes the coupling between frontend and backend.
554+
This removes the coupling between frontend and backend because if you don't need to know the specific
555+
query the client makes to create the server Implementation.
521556

522557
.alert.is-important
523558
:marked
@@ -526,6 +561,7 @@ code-example(language="sh" class="code-shell").
526561
I'm right about "This removes the coupling between frontend and backend".
527562
I was trying to make it clearer by breaking it into smaller ideas, but
528563
I'm not sure what those ideas should be.
564+
:Kapunahele - expanded on that, let me know if that works
529565

530566
:marked
531567
Now, connect the schema to the resolvers with the `makeExecutableSchema` function from
@@ -537,28 +573,42 @@ code-example(language="sh" class="code-shell").
537573
In the constant `schema`, `makeExecutableSchema` has two properties,
538574
`typeDefs` and `resolvers`. Here, you define them with the `typeDefinitions`
539575
and `resolveFunctions` that you created earlier in `in-memory-graphql.ts`.
540-
This way, your app/GraphQL? (Uri - can you correct me here?) knows where to look
541-
for definitions and resolvers.
576+
This way, your GraphQL server knows where to look for definitions and resolvers.
542577

543578
:marked
544579
Now that you have an executable schema, execute it using the `graphql`
545580
library and export it so you can use it with the Apollo Client.
546581
First, `npm install`:
582+
code-example(language="sh" class="code-shell").
583+
npm install graphql --save
547584

548585
.alert.is-important
549586
:marked
550587
Uri: can you provide the npm install command?
588+
:Kapunahele - done
551589

552590
:marked
553591
Next, add an import statement for `execute`.
554592

555593
+makeExample('heroes-graphql/ts/src/app/in-memory-graphql.ts', 'import-graphql', 'in-memory-graphql.ts (excerpt)')
594+
:marked
595+
Now create a new `networkInterface` class and call it `InBrowserNetworkInterface`.
596+
597+
That class will have a `schema` property which it will initialize in the constructor.
556598

599+
Then create a `query` function that will recieve a query as a variable and execute that query using
600+
`graphql` execute function against the schema property.
601+
602+
You send empty objects to the `rootValue` and `contextValue` arguments of the function and send the
603+
`variables` and `operationName` arguments that are related to the query request.
604+
605+
Now export the new `InBrowserNetworkInterface` class in order to import it to Apollo Client.
557606
.alert.is-important
558607
:marked
559608
Uri: Could you explain what's happening in the below?
560609
This will probably take 2-3 short paragraphs. Just a
561610
general tour from top to bottom.
611+
:Kapunahele - let me know if that works
562612
+makeExample('heroes-graphql/ts/src/app/in-memory-graphql.ts', 'execute-and-export', 'in-memory-graphql.ts (excerpt)')
563613
:marked
564614
Now all that's left is to connect the new in-memory server to the Apollo Client configuration
@@ -578,18 +628,21 @@ code-example(language="sh" class="code-shell").
578628
:marked
579629
Uri: Let's add a conclusion showing what was accomplished in the doc.
580630
Maybe something like (please add anything I've missed):
631+
:Kapunahele - done, but not sure if its enough?
581632

582633
.l-main-section
583634
:marked
584635
## Conclusion
585636

586637
This cookbook covered:
587638

639+
- What is GraphQL and why it can benefit Angular developers.
588640
- How to create a basic GraphQL query.
589641
- How to create a basic GraphQL mutation.
590642
- How to build a GraphQL server.
643+
- Resources to dive deeper.
591644

592-
645+
593646

594647
.l-main-section
595648
<a id="example"></a>
Loading

0 commit comments

Comments
 (0)