{"id":15487147,"url":"https://github.com/arjunyel/angular-apollo-example","last_synced_at":"2025-04-22T15:45:30.091Z","repository":{"id":46587566,"uuid":"137690344","full_name":"arjunyel/angular-apollo-example","owner":"arjunyel","description":"An example of GraphQL queries/mutations with Angular Apollo Boost.","archived":false,"fork":false,"pushed_at":"2018-09-24T07:23:12.000Z","size":289,"stargazers_count":37,"open_issues_count":1,"forks_count":13,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-03-29T16:34:30.771Z","etag":null,"topics":["angular","apollo-client","apollo-codegen","grahpql","graphql-example","graphql-tutorial"],"latest_commit_sha":null,"homepage":"https://youtu.be/Wc7bJ2uv694","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/arjunyel.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-06-17T22:10:44.000Z","updated_at":"2023-12-20T04:20:05.000Z","dependencies_parsed_at":"2022-07-20T04:02:23.042Z","dependency_job_id":null,"html_url":"https://github.com/arjunyel/angular-apollo-example","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arjunyel%2Fangular-apollo-example","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arjunyel%2Fangular-apollo-example/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arjunyel%2Fangular-apollo-example/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arjunyel%2Fangular-apollo-example/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/arjunyel","download_url":"https://codeload.github.com/arjunyel/angular-apollo-example/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250271530,"owners_count":21403210,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["angular","apollo-client","apollo-codegen","grahpql","graphql-example","graphql-tutorial"],"created_at":"2024-10-02T06:21:30.104Z","updated_at":"2025-04-22T15:45:30.065Z","avatar_url":"https://github.com/arjunyel.png","language":"TypeScript","readme":"# angular-apollo-example\n\nAn example of GraphQL queries/mutations with Angular Apollo Boost.\n\n## Initial setup\n\nWe start with our [Apollo server from last time](https://github.com/arjunyel/firestore-apollo-graphql), placing the files in the backend folder. Set it up and run the server\n\n```bash\nnpm run serve\n```\n\nGenerate a new Angular app and install dependencies\n\n```bash\nng new frontend\ncd frontend\nng add apollo-angular\n\nnpm install --save-dev graphql-code-generator\nnpm install --save-dev graphql-codegen-apollo-angular-template\nnpm install --save-dev graphql-codegen-introspection-template\n```\n\nBecause Apollo Angular supports schematics, it creates a ready to use setup for you:\n\nInside the graphql module setup the GraphQL endpoint:\n\n```diff\nimport {NgModule} from '@angular/core';\nimport {ApolloModule, APOLLO_OPTIONS} from 'apollo-angular';\nimport {HttpLinkModule, HttpLink} from 'apollo-angular-link-http';\nimport {InMemoryCache} from 'apollo-cache-inmemory';\n\n- const uri = ''; // \u003c-- add the URL of the GraphQL server here\n+ const uri = 'http://localhost:4000';\n\nexport function createApollo(httpLink: HttpLink) {\n  return {\n    link: httpLink.create({uri}),\n    cache: new InMemoryCache(),\n  };\n}\n```\n\nAnd that's it! The GraphQL Module has been already added to the AppModule.\n\n## Setup Query\n\nLets setup our GraphQL query that retrieves all the tweets. In `src/app/graphql` directory first we create a file called `tweets.graphql` with our tweet query:\n\n```graphql\nquery tweets {\n  tweets {\n    id\n    text\n    likes\n  }\n}\n```\n\nOne of the most useful tools to work with GraphQL is [GraphQL Code Generator](https://github.com/dotansimha/graphql-code-generator) which will generate types for our queries and also a [ready to use services](https://www.apollographql.com/docs/angular/basics/services.html) introduced in Apollo Angular v1.2.0.\n\nTo start out with, we point gql-gen at our GraphQL server to generate a schema.json file.\n\n```bash\nnpx gql-gen --schema http://localhost:4000 --template graphql-codegen-introspection-template --out schema.json\n```\n\nNow that we have our schema we have code-gen read the graphql files to see which documents we have\n\n```bash\nnpx gql-gen --schema schema.json --template graphql-codegen-apollo-angular-template --out src/app/graphql/index.ts src/app/graphql/*.graphql\n```\n\nNow let's add those commands to npm scripts to make the whole process easier. First one, under `graphql:introspect`, the second one will be `graphql:generate`.\n\nWith Apollo Angular and GraphQL Code Generator you don't have to manually inject `Apollo` service and use generated types in every of your query or mutation.\n\nNow lets add a class property, a tweets observable, and call our query on init\n\n```typescript\nimport { TweetsGQL, Tweets } from './graphql';\n\nexport class AppComponent implements OnInit {\n  tweets: Observable\u003cTweets.Query\u003e;\n\n  constructor(private tweetsGQL: TweetsGQL) {}\n\n  ngOnInit() {\n    this.tweets = this.tweetsGQL\n      .watch()\n      .valueChanges.pipe(map(tweets =\u003e tweets.data));\n  }\n}\n```\n\nThe `watch` method is going to update our observable whenever the underlying Apollo store on our client is updated, even from another query. We'll see that in the next section when we go over optimistic updates.\n\nIn our app.component.html lets output our tweets and a button/likeTweet function we'll cover in the next section to like a tweet.\n\n```html\n\u003cdiv *ngFor=\"let tweet of (tweets | async)?.tweets\"\u003e\n  {{tweet.text}}\n  \u003cion-icon name=\"flame\" (click)=\"likeTweet(tweet.id, tweet.likes, tweet.text)\"\u003e\u003c/ion-icon\u003e\n  {{tweet.likes}}\n\u003c/div\u003e\n```\n\nI used [Ionicons](https://ionicons.com/) for the button, when we use web components make sure to add\n\n```typescript\nschemas: [CUSTOM_ELEMENTS_SCHEMA];\n```\n\nin our app.module.ts. When you run the app you should now see tweets displayed on the screen!\n\n## Setup Mutation\n\nLets setup a Mutation on our backend that increments the likes on a tweet by 1. Jump into the backend/src/index.ts file and add the mutation to the typeDefs:\n\n```typescript\nconst typeDefs = gql`\n\n  ...\n\n  type Mutation {\n    likeTweet(id: ID!): Tweet\n  }\n`;\n```\n\nThen we code our mutation in the resolver, note that in a real firebase application you would use a transaction to increment the likes. In our example we are just setting the variable, refetching it, and returning.\n\n```typescript\nconst resolvers = {\n\n  ...\n\n  Mutation: {\n    likeTweet: async (_, args: {id: string} ) =\u003e {\n      try {\n        const tweetRef = admin.firestore().doc(`tweets/${args.id}`);\n\n        // Increment likes on tweet, in real life you'd use a transaction!\n        let tweetDoc = await tweetRef.get();\n        const tweet = tweetDoc.data() as Tweet;\n        await tweetRef.update({ likes: tweet.likes + 1 });\n\n        tweetDoc = await tweetRef.get();\n        return tweetDoc.data();\n      } catch (error) {\n        throw new ApolloError(error);\n      }\n    }\n  }\n};\n```\n\nSave and reload the server\n\n```bash\nnpm run serve\n```\n\nReturn back to our app and lets start setting up the like tweet mutation by create `like-tweet.graphql` file\n\n```graphql\nmutation likeTweet($id: ID!) {\n  likeTweet(id: $id) {\n    id\n    text\n    likes\n  }\n}\n```\n\nMake sure your terminal is in the src/app folder and re-run two npm scripts\n\n```bash\nnpm run graphql:introspect\nnpm run graphql:generate\n```\n\nNow with our types and services we are ready to write the mutation function\n\n```diff\n- import { TweetsGQL, Tweets } from './graphql';\n+ import { TweetsGQL, Tweets, LikeTweetGQL } from './graphql';\n```\n\n```typescript\nconstructor(\n  private tweetsGQL: TweetsGQL,\n  private likeTweetGQL: LikeTweetGQL\n) {}\n\nlikeTweet(id: string, likes: number, text: string) {\n  this.likeTweetGQL.mutate({\n    id\n  }).pipe(\n    tap((data) =\u003e console.log(data.data))\n  ).subscribe();\n}\n```\n\nClicking on the button should now increment the likes, congrats you've created a GraphQL mutation!\n\nYou'll notice that even though we didn't tie our query to our tweets observable, it still updated the number with the return from the server. This is because under the hood, Apollo client has its own store where it keeps track of things and one queries result can update another. We can use this to implement optimistic updates.\n\n### Optimistic Mutation\n\nCurrently when we update the likes it will wait for the server response to update. However for a great user experience we might want to update the UI immediately while the update happens through the network, this is an example of optimistic UI.\n\nWe do this by telling Apollo the type, ID, and values of the object we're going to update. Apollo can update the local store immediately, then when the server response comes it will overwrite it in the store. Change the mutate function:\n\n```typescript\nthis.likeTweetGQL\n  .mutate(\n    {\n      id,\n    },\n    {\n      optimisticResponse: {\n        __typename: 'Mutation',\n        likeTweet: {\n          __typename: 'Tweet',\n          id,\n          likes: likes + 1,\n          text,\n        },\n      },\n    },\n  )\n  .pipe(tap(data =\u003e console.log(data.data)))\n  .subscribe();\n```\n\nYou can use your browser's dev tools to slow down your internet connection and see that now when you click the button the number changes instantly! Have fun!\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farjunyel%2Fangular-apollo-example","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Farjunyel%2Fangular-apollo-example","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farjunyel%2Fangular-apollo-example/lists"}