{"componentChunkName":"component---src-templates-blog-post-js","path":"/intro-to-nodejs-part-6/","result":{"data":{"site":{"siteMetadata":{"title":"tech-blog","author":"Alamgir Qazi"}},"markdownRemark":{"id":"94c0fe2c-9ca7-51c3-9c5c-05b8917ae292","excerpt":"This is the part 6 of post Intro to Nodejs - part 5. In this post, we will integrate our Books API with all CRUD (Create, Read, Update and…","html":"<p>\n  <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/tech-blog/static/a717eafa290bf333c4dd1c86076c5b9e/d9199/node-js.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n  \n  <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 50%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAACKElEQVQoz32Sz2vTYBjHnzfVHedglzpRUUSTTE3UJq9jS9I0s/h7BwXdZbUyRUS9+A8sWZqijrGDN0+iB0U8CP4Nw7Vqi9OLStllIHrx5kWI3ydpvWngy/O27/N+np9E//m8sk2ua5ED4ayUfUkD/fMbOAQnJdXCI7SwqlPc0ShqaVSdscgtWzTllDL4wNevSJo+ZVM9MSlc06nR1WjhjUpLX8YzoJJFr0hlfvkwLb7TlLClKotvNcU+OAFQBhmBbkIFSMC/gP+VNCWK32uCgZBY+poD8+iIeqVhEEAUtlWKYE9fKgm+v3/3Hvt9h1+RA0wck2iFpEe/D1Ccw4YYCqDCjgH02g9kpZ4YFLU1B1k+gfXrTYP8aWnxPQPLFXsYQMuZlC9hq5UTNleko0UeNI6StzHwF/TM8+S3WmgW4476A9mlsD+vrxhjyKSH7B+XfXsT572AbpyfK7XxZvXGQ2M0WVdnUPZVAO8kH/RhBm6cnbW3Ati9eOvorrir9vrAzWvLZtFz5Wf4vIB6AI71gc+Dqtz+Kt29BRkybB66DeAIA/fjESH9fUQXlOYnVYXTA0zZqDdMLtmEz1NIIigP6RBKXoHdeWbWomhN34H+TUJ7eDvyoQCIhzREASUfeSAq95JqkSnQ278r47q24KFMHcfZyVcoauk86Ww4zfUcKPgSD8Uo+QwUUVstoGwxF5m8c9ma9Ncr80c/+TdVz9kMFBmwo4k0vUx/ANst4OwYAzGqAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n    >\n      <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\"\n        alt=\"Intro To Node.js\"\n        title=\"\"\n        src=\"/tech-blog/static/a717eafa290bf333c4dd1c86076c5b9e/fcda8/node-js.png\"\n        srcset=\"/tech-blog/static/a717eafa290bf333c4dd1c86076c5b9e/12f09/node-js.png 148w,\n/tech-blog/static/a717eafa290bf333c4dd1c86076c5b9e/e4a3f/node-js.png 295w,\n/tech-blog/static/a717eafa290bf333c4dd1c86076c5b9e/fcda8/node-js.png 590w,\n/tech-blog/static/a717eafa290bf333c4dd1c86076c5b9e/efc66/node-js.png 885w,\n/tech-blog/static/a717eafa290bf333c4dd1c86076c5b9e/d9199/node-js.png 960w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n    </span>\n  </span>\n  \n  </a>\n    </p>\n<p>This is the part 6 of post <a href=\"https://alamgirqazi.github.io/tech-blog/intro-to-nodejs-part-5/\">Intro to Nodejs - part 5</a>.</p>\n<p>In this post, we will integrate our Books API with all CRUD (Create, Read, Update and Delete) operations with our Ionic App.</p>\n<p>So lets get started.</p>\n<p>We will use that Node.js app we used for User Login and Signup.</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">git clone https://github.com/alamgirqazi/intro-to-nodejs-part4.git</code></pre></div>\n<p>I’ll quickly do a couple of things.</p>\n<ol>\n<li>change the folder name to node-part6</li>\n<li>delete .git folder.</li>\n<li>update package.json name to node-part6</li>\n<li>yarn install or npm install</li>\n</ol>\n<p>Before we start our app, we need to create a local .env file.</p>\n<p>lets create that and add contents from sample.env file.</p>\n<p>my .env file looks like</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">JWT_KEY = SecretjwtKey\nPORT = 3000\n\nmongoCon = mongodb://localhost:27017/bookyapp</code></pre></div>\n<p>Lets start our app</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">nodemon app</code></pre></div>\n<p>Great, our app is up and running.</p>\n<p>Previously, we set up a complete Books API on Node.js in part 4.</p>\n<p>Lets use that with the Ionic app we built in part 5.</p>\n<p>now, separately, I will use that ionic app. You can optionally clone from here (<a href=\"https://github.com/alamgirqazi/booky-ionic\">https://github.com/alamgirqazi/booky-ionic</a>) but I will just use from the previous part.</p>\n<p>lets run our app via</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">ionic serve</code></pre></div>\n<p>lets create a new page named books</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">ionic g page books</code></pre></div>\n<p>first, we need to display a list of books that are already in the database</p>\n<p>we need to create a user service. Instead of <code class=\"language-text\">ionic g service user</code> , I’ll just copy and paste the user.service.ts we already have.</p>\n<p>Here’s how my books.service.ts looks like</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">import { HttpClient, HttpHeaders } from '@angular/common/http';\n\nimport { BookyConfig } from '../booky.config';\nimport { Injectable } from '@angular/core';\nimport { Observable } from 'rxjs';\n\n@Injectable({\n  providedIn: 'root'\n})\nexport class BooksService {\n  constructor(private http: HttpClient) {}\n\n  public getAllBooks(): Observable&lt;any> {\n    const url = BookyConfig.getPath() + '/books';\n\n    return this.http.get(url);\n  }\n}</code></pre></div>\n<p>Ok, lets head over to books.page.html and write some HTML.</p>\n<p>what we need now is to display a list. We’ll use <code class=\"language-text\">ion-list</code>.</p>\n<p>Here’s books.page.html</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">&lt;ion-header>\n  &lt;ion-toolbar color=\"primary\">\n    &lt;ion-title class=\"ion-text-center\">Booky&lt;/ion-title>\n  &lt;/ion-toolbar>\n&lt;/ion-header>\n\n&lt;ion-content color=\"\">\n\n  &lt;ion-list>\n    &lt;ion-item *ngFor=\"let book of books\">\n      &lt;ion-thumbnail slot=\"start\">\n        &lt;ion-img [src]=\"book.image_url\">&lt;/ion-img>\n      &lt;/ion-thumbnail>\n      &lt;ion-label>{{book.name}}&lt;/ion-label>\n      &lt;ion-icon name=\"create\" slot=\"end\">&lt;/ion-icon>\n      &lt;ion-icon name=\"trash\" slot=\"end\">&lt;/ion-icon>\n    &lt;/ion-item>\n  &lt;/ion-list>\n\n&lt;/ion-content></code></pre></div>\n<p>We need to add TS code now</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">import { Component, OnInit } from '@angular/core';\n\nimport { BooksService } from '../../sdk/custom/books.service';\n\n@Component({\n  selector: 'app-books',\n  templateUrl: './books.page.html',\n  styleUrls: ['./books.page.scss']\n})\nexport class BooksPage implements OnInit {\n  loading = false;\n  books: Books[] = [];\n  constructor(private booksService: BooksService) {}\n\n  ngOnInit() {\n    this.getAll();\n  }\n\n  getAll() {\n    this.loading = true;\n\n    this.booksService.getAllBooks().subscribe(\n      data => {\n        console.log('got response from server', data);\n        this.loading = false;\n        this.books = data.data.docs;\n      },\n      error => {\n        this.loading = false;\n        console.log('error', error);\n      }\n    );\n  }\n}\n\n// Intefacing is Optional\n\ninterface Books {\n  name: string;\n  ibn: string;\n  image_url: string;\n  author: string;\n  is_deleted: boolean;\n}</code></pre></div>\n<p>You must be familiar with most the code above. We added one extra thing. We added an interface for Books. This helps us catch errors during compile time and not run time.</p>\n<p>So this is what it looks like</p>\n<p>\n  <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/tech-blog/static/9205a02ef458d382525947d1311aaa93/4c0ad/booky3.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n  \n  <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 341px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 161.48648648648648%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAgCAYAAAASYli2AAAACXBIWXMAABJ0AAASdAHeZh94AAACIklEQVRIx+1VzW7TQBD2W3BHAoQEr8EZCQm1gnLhijgAbanEC3BCSmiLuCFBK56AF+AtkighIc6vnSqOvd5drz9mduMQNU6BwgllpE+znp399vvGku2dfk3x9IPCwanE/skq9gi7nxz2Ttb3vPqs0AsEvOcfFa48AW7uA9d3f+IG4eoz4M5rYOcdcK8C3HoJXHvh9pb7uHb7AKh3ibDyReDumxwPDzW232psVRW2KsrlqsajY43H7x0eHGpb2666XKzvU//OkUJ7kMCLYoF+GCGKJWZCQ2aAMgTKQhrEqaG6Q0LrRM6RZkg1kKrc9nOOYyKUaYre2RDGEENuMAkD9PwuBv0eqICLYhZNIZIYfvc7ptMzSCnhpUTIYfIcWZbRRoTRaIQgDOmSHFQmFNmBezm4V2mNIfXPZjMwFxFKYtbQtMGE58ORrcIYs9IbxzE8IVK0hj6kUjBEyMXJZIIoikjB1B4uI+YQQlhVIbnhc3OFKTWYxa1st9lsYjAYwPf9hZKCZHnNRHy+1WpZEYpEeTxInj3bLbNcFussJ0niLH8b9a3lgpRvWgbPl7H8zMG9vGZRXOcRWMuJFItb2SpbYLuNRgPtdhudTsdmrtdqNYzHY0s4mr/der2OIAicZTfDfHFb2fDX1YoRsRCGtWxneO5Q0fArFL1FXiH8m+DzaxX+KdYSXlbZhnBDuCH8zwkv+rj+E4W/o3qFkH/0ZV/pyyr8ATJJozi9BiJhAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n    >\n      <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\"\n        alt=\"booky page\"\n        title=\"\"\n        src=\"/tech-blog/static/9205a02ef458d382525947d1311aaa93/4c0ad/booky3.png\"\n        srcset=\"/tech-blog/static/9205a02ef458d382525947d1311aaa93/12f09/booky3.png 148w,\n/tech-blog/static/9205a02ef458d382525947d1311aaa93/e4a3f/booky3.png 295w,\n/tech-blog/static/9205a02ef458d382525947d1311aaa93/4c0ad/booky3.png 341w\"\n        sizes=\"(max-width: 341px) 100vw, 341px\"\n      />\n    </span>\n  </span>\n  \n  </a>\n    </p>\n<p>Nice. we’re able to get the data from the API and display it here. GET looks set.</p>\n<p>Few things we should add here. THere’s no loading display. we can use ion-skeleton for this.</p>\n<p>we are keeping the loading state in the variable <code class=\"language-text\">loading</code>. We are manually turning it true and false. We display the ion-skeleton only when its loading.</p>\n<p>lets update our HTML.</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">&lt;ion-header>\n  &lt;ion-toolbar color=\"primary\">\n    &lt;ion-title class=\"ion-text-center\">Booky&lt;/ion-title>\n  &lt;/ion-toolbar>\n&lt;/ion-header>\n\n&lt;ion-content color=\"\">\n  &lt;div *ngIf=\"!loading\">\n\n    &lt;ion-list>\n      &lt;ion-item *ngFor=\"let book of books\">\n        &lt;ion-thumbnail slot=\"start\">\n          &lt;ion-img [src]=\"book.image_url\">&lt;/ion-img>\n        &lt;/ion-thumbnail>\n        &lt;ion-label>{{book.name}}&lt;/ion-label>\n        &lt;ion-icon name=\"create\" slot=\"end\">&lt;/ion-icon>\n        &lt;ion-icon name=\"trash\" slot=\"end\">&lt;/ion-icon>\n      &lt;/ion-item>\n    &lt;/ion-list>\n  &lt;/div>\n\n  &lt;div *ngIf=\"loading\">\n\n\n    &lt;ion-list>\n\n\n      &lt;ion-item *ngFor=\"let item of skeletonlist\">\n        &lt;ion-thumbnail slot=\"start\">\n          &lt;ion-skeleton-text animated>&lt;/ion-skeleton-text>\n        &lt;/ion-thumbnail>\n        &lt;ion-label>\n          &lt;h3>\n            &lt;ion-skeleton-text animated style=\"width: 50%\">&lt;/ion-skeleton-text>\n          &lt;/h3>\n          &lt;p>\n            &lt;ion-skeleton-text animated style=\"width: 80%\">&lt;/ion-skeleton-text>\n          &lt;/p>\n          &lt;p>\n            &lt;ion-skeleton-text animated style=\"width: 60%\">&lt;/ion-skeleton-text>\n          &lt;/p>\n        &lt;/ion-label>\n      &lt;/ion-item>\n\n    &lt;/ion-list>\n  &lt;/div>\n&lt;/ion-content></code></pre></div>\n<p>This is how the loading looks. Kinda nice right.</p>\n<p>\n  <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/tech-blog/static/9f30b9cc52316468ca3ece1d424054f8/1efb2/loading.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n  \n  <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 370px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 159.45945945945945%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAgCAYAAAASYli2AAAACXBIWXMAABJ0AAASdAHeZh94AAACMklEQVRIx+1VzYrUQBCeV/DgUXFZT558FQ8+gCAogu7MuviDou4bCIIgIujsuop68uZVvPkkjvOTmUw6nf7JZ1WSWntispsREQ8WfNNJVfVXVV1dk541GvufNe68MXj0IcPD96tg3QNa778r17p9l+y3Dgw+ftVArtHzRuHSM4uT14DNm8CZQYmNbeDUFnD+HnDxCXDhMXDuNnC6X9o2BiXO7gAnrgJ331oAKXomU3j6SePKC4/BnsONV5bgsDWk52G5bu877Lx26O9ZXH9pK58S/aHF5ecOB18oQ0+ESinkjl5cCm8SimJK5NkqPAGOkAfwFXLiyKBURZhqjfFkim+j71CpRkKGOF4iXiYBloU+1RlS8mFY5+GJNydkmSFdRajJabFYIIoiMmQF2KgpUAhV6XJi8N4XK4PFmICQCZxzsNYWjvzchDpJSCxJVBnqIrvJZFI8syFJkl/ANg7K2TCYTGQlQ3acTqcYj8c/yyN9E3gTk0o1jYRdS5ayRcLyV0rmlziOMZ/Pi0hhU8KVAzKBkLc2hTfw+Y1Go0LJuiVdkzr4HCUB3nNkyXJuEl3OKQRv4jUst7HL4d1jMim7DraFZJ1Lbrs24tup5HpT6lMijWEbEx07KXJGx01KveTWSZnNZocXmw3SVQG/rzUpUTQ7HL22SWFiaZzcyU6T0vUPorVkZg8ljFyX+pVpbIoQhg5dpRPhujiScF35T/gXCP+9LvPPH81QZlC+Jb8D+ZAx1w+I7aGuvannywAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n    >\n      <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\"\n        alt=\"loading\"\n        title=\"\"\n        src=\"/tech-blog/static/9f30b9cc52316468ca3ece1d424054f8/1efb2/loading.png\"\n        srcset=\"/tech-blog/static/9f30b9cc52316468ca3ece1d424054f8/12f09/loading.png 148w,\n/tech-blog/static/9f30b9cc52316468ca3ece1d424054f8/e4a3f/loading.png 295w,\n/tech-blog/static/9f30b9cc52316468ca3ece1d424054f8/1efb2/loading.png 370w\"\n        sizes=\"(max-width: 370px) 100vw, 370px\"\n      />\n    </span>\n  </span>\n  \n  </a>\n    </p>\n<p>Once thing you can notice when the images load is that the broken image looks really bad. How about we add a custom icon in case the image isn’t there?</p>\n<p>Download any book icon from the internet. Or you can use this</p>\n<p>\n  <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/tech-blog/static/dfb9bf0483d9def81af41239a72b7042/01e7c/book.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n  \n  <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 512px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 100%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAADIUlEQVQ4y41UW09TQRCenm4RhaAg0UQicpVLQUMv0JY9t164CEEqiKAiBUFQUIMxMSGoMeoDUaPxwcT4oD4bf4ov/iH95nQObdEYm3ydOTsz387M7g5ls46RyTjBTMb2kM0ynAq99O1UrPnffjxzEX9AUeKghFgJiSoR/dPmcxjk7+4bWTppW8VNqyoy7OHQsGOrpGWFWOe1QdMKpQ/EIFMlGZZ2ZSQQuLc6GqjrTdHRcIrqAaqKEDUPUX1fca2mJ0kzE66RtK3QSK4ioX3CYA5kMW1VUUOMugZ1XUtE585EdAFYao/pptao7oK+wt8tUa3Pp8xqon6KImZsZL8FRUImi8PQgAzgnEHQDrAIjIF4tDmi30F/JptMCPEOfAc4hluRK5Ze7CH3h1oTBKcZBH8TsmvADWAWuA0sA/NiWwA24PsdpElqGSJulUeIAwjmL7gGpw6Hr3B8DuSFbA6YBtal/LysLQEX4f8B2KOmQdKOHfJ6iL6FqD1B6FEYxi9wXANWy+SckHNWV4GbnJ2QbiPmU0dMnyQ6SynbClJ02Aod7k5yufMwfoS8LuVd4RYwSVtMn8aG3WK7JOSccYGTQNl2NTgGwEUuSi7k0waMj4EXQnRLGs9yuyOuT4CwE/pDyXxF5AII30De4TPA3VVEbQlCBs3cDw6Wxs9i1xiXEk6YR/haYGPVmzBr+ArxQUiWvPkuYl/3DJm1v34WyLuocBiB4SkM7yEfAJvAlpzuJt9B3gD6PVnbEp9HiHkL+QT2+DF+BPzHdwqGV+K4IaXyya6xI+Rd7hf0BJcn5a6LvinVLR/vB+FSPh3AyzjaGdeNfHUK+YwxiufUh1JB4MoFtiG5il3okXNJs3pu0jUYrKPHjb0o+fKkG/Du4Y+XU8S/cfQK90mZrq1m8Vb5PaNnp+Rkp3jj2p4U8YaeHzA97hpEDbSzmAswl/dSbBBYAE8ZTBHFJ8+SJw5R2GsL9/rz/fGATBrlCjjGlNjyefjHMPVHE2fBreDBwRuX28sGq4/icCgOx/0RpkrgNbtiAMuaKo28ijhvOBh/h31At//DzzF+A8rWQuQ/hNLdAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n    >\n      <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\"\n        alt=\"book\"\n        title=\"\"\n        src=\"/tech-blog/static/dfb9bf0483d9def81af41239a72b7042/01e7c/book.png\"\n        srcset=\"/tech-blog/static/dfb9bf0483d9def81af41239a72b7042/12f09/book.png 148w,\n/tech-blog/static/dfb9bf0483d9def81af41239a72b7042/e4a3f/book.png 295w,\n/tech-blog/static/dfb9bf0483d9def81af41239a72b7042/01e7c/book.png 512w\"\n        sizes=\"(max-width: 512px) 100vw, 512px\"\n      />\n    </span>\n  </span>\n  \n  </a>\n    </p>\n<p>download this. copy it to <code class=\"language-text\">SRC -> Assets -> Icon</code>.</p>\n<p>lets display it incase our image doesnot load.</p>\n<p>we need to add its path in book.page.ts</p>\n<p>here’s a quick hacky way</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">       &lt;ion-thumbnail slot=\"start\">\n          &lt;ion-img *ngIf=\"book.image_url &amp;&amp; book.image_url!='null'\" [src]=\"book.image_url\">\n          &lt;/ion-img>\n          &lt;ion-img *ngIf=\"!book.image_url ||  book.image_url=='null' \" [src]=\"'assets/icon/book.png'\">\n          &lt;/ion-img>\n        &lt;/ion-thumbnail></code></pre></div>\n<p>Now it looks much cleaner</p>\n<p>\n  <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/tech-blog/static/64c10663c8d0dd0b70bf680947141d49/2b727/cleaner.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n  \n  <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 368px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 108.78378378378379%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAWCAYAAADAQbwGAAAACXBIWXMAABJ0AAASdAHeZh94AAACAUlEQVQ4y+1Sy27TQBTN33RZhLooBTZ8AmxYsGaBkFiBxDtQ8QEIiRUC8SlIFASoCWnjplFDm6bGdgiJHzieGXvGhztTOS9IBFJ3cKWjuTM+98w9d1xKBUf9kONtg+H97q/YoPM3FqF+nP+Oo2utDkeaCpQykeDqiwxLt4CV+8Dpe2Ms3wHOrwOXngIXCatl4NTdac7KA2DpJnDtpUSeMZRSErz+SlCxwtlHEmvlMVYfSlx4onD5mcKV58rkZ8qap7CmQZxzjyWWbyvceJ1CpQlKLEnQcjh2HWDPA3ZsZfKmCzS+Kmx3MlQPJCqEekfCOiqQ0ffc8BvE3/cEOCPB4XAIQKL1pYnPW1VAcbDYRxx+p5xhUUgRG37Qp06UAGNkOaEOE8ZR22niQ6UGP4jQ/dZD58hG9CNGrgtVDjUBvc/pQxCEJCJg2w6tfCyYpunCTpRSJJBPQZ9NRpZl0FrGsqRNs7WPypYFIQR836fbAwwGA7PXMSuoI45jcM7R7XYNb9ShPqxuW9j4uIkgDOF5riG5rmtunSeoL9W1tm2b9Y8tzxvDfMuSXvmgjZrVgCDxkLqMomhkXed6LXD8ZwCFu2I0ow4ZHer5vfu0Sa8cotfrod/vG8ue503ljuMYUR1aSIu02+2Ts1zMc2R5UnB28IswyT8RwVnxuYJ/G/8F/0XBn0lNiXqztPHvAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n    >\n      <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\"\n        alt=\"cleaner\"\n        title=\"\"\n        src=\"/tech-blog/static/64c10663c8d0dd0b70bf680947141d49/2b727/cleaner.png\"\n        srcset=\"/tech-blog/static/64c10663c8d0dd0b70bf680947141d49/12f09/cleaner.png 148w,\n/tech-blog/static/64c10663c8d0dd0b70bf680947141d49/e4a3f/cleaner.png 295w,\n/tech-blog/static/64c10663c8d0dd0b70bf680947141d49/2b727/cleaner.png 368w\"\n        sizes=\"(max-width: 368px) 100vw, 368px\"\n      />\n    </span>\n  </span>\n  \n  </a>\n    </p>\n<p>Ok. Lets add a book to our database.</p>\n<p>we need an Add button. and we need to open another page or maybe a popup. A popup seems fine.</p>\n<p>lets update our toolbar</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\"> &lt;ion-toolbar color=\"primary\">\n    &lt;ion-title class=\"ion-text-center\">Booky&lt;/ion-title>\n    &lt;ion-button slot=\"end\" color=\"success\">\n      Add New &lt;/ion-button>\n  &lt;/ion-toolbar></code></pre></div>\n<p>Lets add a new add new page</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">ionic g page books/addnewbook</code></pre></div>\n<p>We can see that the component has been created.</p>\n<p>\n  <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/tech-blog/static/0fa4c4831f52ce12d165383562866bff/2fbbf/newbook.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n  \n  <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 425px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 80.4054054054054%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAYAAAAWGF8bAAAACXBIWXMAABJ0AAASdAHeZh94AAACO0lEQVQ4y31U2W7bMBD0RxQoUBSwrZOXLuuWbCOOmzZtHvMP/f8/mO6SOiIkzcNgRUoczu7sancINYI4wfj4G/XDHbKtIesae09aHHyFI33zGQ6BgicMRFZjxws/NsiqAd39D0TbQPct4lNpicM0X4gd5ARlibaE1UQYGUTmhOtwJeISauxhGOceoqrgyxSBzggpwiRHYDK7fqvwGOst4XeK1zDCkGUQRKZZ6dBZtaqbnglmXPdmslmhLJqVcB9ptFGJIqmgznSoay2BosipM4GiS3gtymopxduUF0KPCP1QYW96+AWraO1Bp2QibGfClThMi0Uhp7wSkst+IPC1fsahvSMdm016slnT5z0mi7ICvko3KcdZ6QiPpDAIJIL8Cr++wPT1qpDUiLpaVEmKIZE55wmhc98TJIpM21mnSKESKV6FguLDU51sHfvOYnY9TChNz5WJhRxDQqBtJ3AH7HROjp4GlITXU4/ydkd1/2Fj/fSE5tdPFJcbTDFsYM8xCheT6oysu2IXCOopVUDrHC9ZQqro5TA4jKOF6QfY7z6CdJH72NXQ1kEjIvmPVGTZ1FPftUguvX3mGu75u8mAQyA3kd+xKdz4iylxnKKPVwO4flwzN37FpzPtXE7sBE19SC9I9rfyBkmjxm2ipkmZp4Tb5H+kC6G2hBoeSd+bFl+e/0INve01cxmQPpyt475MqFfN8jN4R0gXWZdpeiyhTwoFuewNL3aTEeUnN2LUCss0zD+CDxQeiYMv/Qc5AOYM2I2iXgAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n    >\n      <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\"\n        alt=\"New book\"\n        title=\"\"\n        src=\"/tech-blog/static/0fa4c4831f52ce12d165383562866bff/2fbbf/newbook.png\"\n        srcset=\"/tech-blog/static/0fa4c4831f52ce12d165383562866bff/12f09/newbook.png 148w,\n/tech-blog/static/0fa4c4831f52ce12d165383562866bff/e4a3f/newbook.png 295w,\n/tech-blog/static/0fa4c4831f52ce12d165383562866bff/2fbbf/newbook.png 425w\"\n        sizes=\"(max-width: 425px) 100vw, 425px\"\n      />\n    </span>\n  </span>\n  \n  </a>\n    </p>\n<p>We need to define it in books.module.ts</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">import { AddnewbookComponent } from './addnewbook/addnewbook.component';\nimport { BooksPage } from './books.page';\nimport { BooksPageRoutingModule } from './books-routing.module';\nimport { CommonModule } from '@angular/common';\nimport { FormsModule } from '@angular/forms';\nimport { IonicModule } from '@ionic/angular';\nimport { NgModule } from '@angular/core';\n\n@NgModule({\n  imports: [CommonModule, FormsModule, IonicModule, BooksPageRoutingModule],\n  declarations: [BooksPage, AddnewbookComponent],\n  entryComponents: [AddnewbookComponent]\n})\nexport class BooksPageModule {}</code></pre></div>\n<p>I added one more thing here. <em>entryComponents</em>.</p>\n<h3>EntryComponents</h3>\n<p>An entry component is any component that Angular loads imperatively by type.</p>\n<p>A component loaded declaratively via its selector is not an entry component.</p>\n<p>We will load this component not via HTML but by TS so we need to add it to entryComponents.</p>\n<p>Ok, lets add a method to that <em>Add new</em> Button on the toolbar.</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">&lt;ion-toolbar color=\"primary\">\n    &lt;ion-title class=\"ion-text-center\">Booky&lt;/ion-title>\n    &lt;ion-button slot=\"end\" (click)=\"openAddModal()\" color=\"success\">\n      Add New &lt;/ion-button>\n  &lt;/ion-toolbar></code></pre></div>\n<p>Lets write some code for openAddModal()</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\"> async openAddModal() {\n    const modal = await this.modalController.create({\n      component: AddnewbookComponent\n    });\n    return await modal.present();\n  }</code></pre></div>\n<p>For this to work, we need to update our constructor</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\"> constructor(\n    private booksService: BooksService,\n    private modalController: ModalController\n  ) {}</code></pre></div>\n<p>and also add the imports at the top.</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">import { AddnewbookComponent } from './addnewbook/addnewbook.component';\nimport { BooksService } from '../../sdk/custom/books.service';\nimport { ModalController } from '@ionic/angular';</code></pre></div>\n<p>Ok. lets see it in action.</p>\n<p>\n  <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/tech-blog/static/ad8397a54f900f1966d52b75a4064cf2/928ea/addnewc.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n  \n  <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 549px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 156.75675675675674%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAfCAYAAADnTu3OAAAACXBIWXMAABJ0AAASdAHeZh94AAABKElEQVRIx+2W63KDIBCFff/XtGnqFaGKeD3dxWGiRFNq86MzDeNxucjnWVDHyBiDtm3RdR2klIjjGGmaoqoqaK1trOvaxqZpIIRAkiQoy9JeW1JbKWXHmRHxQFEUyPMcWZZZGEcn18/RF/fzXBZzuC9iKmscJ9JoNQwDaYns/lhmEWXpOBFPYrtx/IbL5d0qSVJcrx/kNsM0zfea15rQ6GXJ+r5HxCelPsl2SbaFlZQKgm7C/TNNooNAwMyy7ZsYugFyxZgOR8UH7En7QF6Po4sJ6dCbuhvj6J6SIKBLeb/+DfBR2nt11z7hcN7Agh0+HRha/CU45fCR66cBg1IOST3YYeib4W9QkMM9p/5NfwQM3ekX8AX8v8C/+Pky+E25A5rVv8kZrYFfO/+MR6fWHfMAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n    >\n      <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\"\n        alt=\"add new component\"\n        title=\"\"\n        src=\"/tech-blog/static/ad8397a54f900f1966d52b75a4064cf2/928ea/addnewc.png\"\n        srcset=\"/tech-blog/static/ad8397a54f900f1966d52b75a4064cf2/12f09/addnewc.png 148w,\n/tech-blog/static/ad8397a54f900f1966d52b75a4064cf2/e4a3f/addnewc.png 295w,\n/tech-blog/static/ad8397a54f900f1966d52b75a4064cf2/928ea/addnewc.png 549w\"\n        sizes=\"(max-width: 549px) 100vw, 549px\"\n      />\n    </span>\n  </span>\n  \n  </a>\n    </p>\n<p>It worked. But there is alot of work to be done.</p>\n<p>Lets add HTML form</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">&lt;ion-header>\n  &lt;ion-toolbar color=\"primary\">\n    &lt;ion-buttons slot=\"start\">\n      &lt;ion-back-button [text]=\"'cancel'\" (click)=\"dismiss()\" defaultHref=\"books\">&lt;/ion-back-button>\n    &lt;/ion-buttons>\n\n  &lt;/ion-toolbar>\n&lt;/ion-header>\n\n&lt;ion-content color=\"\">\n  &lt;form [formGroup]=\"addNewBookForm\">\n    &lt;ion-grid>\n      &lt;ion-row color=\"justify-content-center\">\n        &lt;ion-col class=\"ion-align-self-center\" size-md=\"6\" size-lg=\"5\" size-xs=\"12\">\n          &lt;div class=\"ion-text-center\">\n            &lt;h3>Add New Book&lt;/h3>\n          &lt;/div>\n          &lt;div class=\"ion-padding\">\n            &lt;ion-item>\n              &lt;ion-input formControlName=\"name\" type=\"text\" placeholder=\"Name\">&lt;/ion-input>\n            &lt;/ion-item>\n            &lt;ion-item>\n              &lt;ion-input formControlName=\"ibn\" type=\"text\" placeholder=\"IBN Number\">&lt;/ion-input>\n            &lt;/ion-item>\n            &lt;ion-item>\n              &lt;ion-input formControlName=\"author\" type=\"text\" placeholder=\"author\">&lt;/ion-input>\n            &lt;/ion-item>\n            &lt;ion-item>\n              &lt;ion-input formControlName=\"image_url\" type=\"text\" placeholder=\"image url\">\n              &lt;/ion-input>\n            &lt;/ion-item>\n\n          &lt;/div>\n          &lt;div class=\"ion-padding\">\n            &lt;ion-button size=\"large\" [disabled]=\"addNewBookForm.invalid\" (click)=\"save()\" color=\"primary\" type=\"submit\"\n              expand=\"block\">SAVE !\n            &lt;/ion-button>\n          &lt;/div>\n        &lt;/ion-col>\n      &lt;/ion-row>\n    &lt;/ion-grid>\n  &lt;/form>\n&lt;/ion-content></code></pre></div>\n<p>Let adds the TS code</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">import { Component, OnInit } from '@angular/core';\nimport { FormBuilder, FormGroup, Validators } from '@angular/forms';\n\nimport { ModalController } from '@ionic/angular';\n\n@Component({\n  selector: 'app-addnewbook',\n  templateUrl: './addnewbook.component.html',\n  styleUrls: ['./addnewbook.component.scss']\n})\nexport class AddnewbookComponent implements OnInit {\n  constructor(\n    private modalCtrl: ModalController,\n    private formBuilder: FormBuilder\n  ) {}\n\n  addNewBookForm: FormGroup;\n  loading = false;\n\n  ngOnInit() {\n    this.formInitializer();\n  }\n\n  formInitializer() {\n    this.addNewBookForm = this.formBuilder.group({\n      name: [null, [Validators.required]],\n      ibn: [null, [Validators.required]],\n      author: [null, [Validators.required]],\n      is_deleted: [false, [Validators.required]],\n      image_url: [null]\n    });\n  }\n\n  save() {}\n\n  dismiss() {\n    this.modalCtrl.dismiss({\n      dismissed: true\n    });\n  }\n}\n// Intefacing is Optional\n\ninterface Books {\n  name: string;\n  ibn: string;\n  image_url: string;\n  author: string;\n  is_deleted: boolean;\n}</code></pre></div>\n<p>make sure to add <em>ReactiveFormsModule</em> to the imports of Books.module.ts</p>\n<p>\n  <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/tech-blog/static/1a82202ccd60fab98e86095c2d9a2b4c/48711/addnewpage.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n  \n  <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 459px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 171.6216216216216%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAiCAYAAABfqvm9AAAACXBIWXMAABJ0AAASdAHeZh94AAACgUlEQVRIx+2WW08TQRTH+22MUVEfjTEx+uC730WDguAlauKbhqCS6IvGSsH4LoVSuYgVvIFIgMKDMaX3++7s7O78nZnttnsp0m3xzUn+mbNzdn5zzpzZaUOvFwhOXAPO3gbO3QEu3APO3AL6rgMnO9SpAeDoVWD6u4rQqzmC04PAxfvApQfA5YfA+bvAsX7IhY4fIPFOH9eRK0D0m4LQ0oaC/jDF0ATFYIRiYJziRkTH8CTFMB8T/dCEJv22bY/bujmpy7mru3WEDKoCMD0y0Gqmw2YO2/DNoYRHqKgEBn92yuTzVtfWsfz5K35ubGJuflH2K/w58WkFm1tJidQN5pqnKHwPVVW11masKdEqlQoymQzq9brsi8UiCoUC0um09HnnCCmK0gIGbfbCzt4F1HUdpVJJRmSaZtsIvFl4F3ABDcOQqdRqNQn8G2w/uYAC4gTZ9kFwp98F1DQNqVRKbnw+n0c2mwUhJNCeNoDEty/2ykFT9+1htVqVEnbPe2gXRaiTKnsr7kvZhjgLFERtIxTFyOVyKJfL8lwGPehNoIja4B+jRimvrAZKdf6dmnKsI7WL0H2T2M+dqwkkRJW3y688w/Yew06aIemQGNvas/qkx7eTscZ/FyyoBGr88Go6Q3jRxGgUGJtheOrQi3mGlwuWnseZyz8WYxiZYni7bEeotoBiwsgU8HiaK9oQt8eXgMhHIPwBeDZrjY02/E+4/egd8CbhAIrPy+A5J7YpYj8o3q9TxB2a5WOxNauPe3zi3Rnu+7Krt1J2F6V7+aosjo7ZpRhDOyDrWm0v2P1u4iA/Bf+B/wjYixqXA8FhtSZQXK6HIZGtBAqy+MfQiwRDsP4AuOkg9y0Gf08AAAAASUVORK5CYII='); background-size: cover; display: block;\"\n    >\n      <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\"\n        alt=\"add new component complete\"\n        title=\"\"\n        src=\"/tech-blog/static/1a82202ccd60fab98e86095c2d9a2b4c/48711/addnewpage.png\"\n        srcset=\"/tech-blog/static/1a82202ccd60fab98e86095c2d9a2b4c/12f09/addnewpage.png 148w,\n/tech-blog/static/1a82202ccd60fab98e86095c2d9a2b4c/e4a3f/addnewpage.png 295w,\n/tech-blog/static/1a82202ccd60fab98e86095c2d9a2b4c/48711/addnewpage.png 459w\"\n        sizes=\"(max-width: 459px) 100vw, 459px\"\n      />\n    </span>\n  </span>\n  \n  </a>\n    </p>\n<p>I think this looks real nice. Lets get to the sweet part. Integrating it with our backend.</p>\n<p>We need to save a new book into our database.</p>\n<ol>\n<li>Create a POST method is Books.service.ts</li>\n<li>write save() function just like register function.</li>\n</ol>\n<p>Lets start</p>\n<p>If we see our Nodejs project, books.routes.js file</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">router.post(\"/add\",bookController.addBook);</code></pre></div>\n<p>that means /add for Adding a new book.</p>\n<p>lets write the service function</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">  public addNewBook(data: object): Observable&lt;any> {\n    const url = BookyConfig.getPath() + '/books/add';\n\n    return this.http.post(url, data);\n  }</code></pre></div>\n<p>Lets write the save function</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\"> save() {\n    this.loading = true;\n\n    this.booksService.addNewBook(this.addNewBookForm.value).subscribe(\n      data => {\n        console.log('got response from server', data);\n        this.loading = false;\n      },\n      error => {\n        this.loading = false;\n        console.log('error', error);\n      }\n    );\n  }</code></pre></div>\n<p>lets try this</p>\n<p>\n  <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/tech-blog/static/76b4dbe252c54a967e86da2e1dca52c6/712f7/booksave.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n  \n  <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 70.94594594594594%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAABJ0AAASdAHeZh94AAACJUlEQVQ4y42SyWpUQRSG84T6BOLG8SF8ABe6NEJIu3AZcGFAXIhEEKERQzugSafTQ+7ct+5UdcfuuvV7qm53tBXbFPycGjhfnWnHsi9wcjbG6HyC0+EI48kMtuvDsj0jxw1gO7S3LEztEA8OJO73JO72FG7vK9wh3dqTuPlUoj9ssON5AS6cAGHI4AYJJtYcnh8gTlJwkSNJMsznIYLAw8zy8eJji+fvW+y9KfHkdY5d0rN3EvtHLc5cAgoeY+7PEDPPiIUOwrltbJHHkMsSWcrAM0Y2AtDCLMnRVhFkyfTBXClJwDybIvH6SINjcPbZSERfIdgXY2t+Ch59R57+AE9d1I1EFCdYStVBNI7+0Oe60UDuIPYHYO6AHE9Q8XOU2cjYSoxR0D7PxqjzGQF9LBYSnGeQUkIphbZtjdVqDDDPkaYJ0oQjjiMCUSp1ZR61U9tKlGVhxOmtaRZgUYJmsbyMTEu2vwFtasp0FsJyfLCAQRBcy/epbqJAngsIalCWcUpwSapWdVMbMsCyqlCLhupVoEhTKnKFRVFQM6T5VafSORCm4JgEEgd94OUnhVcDhcNjRWeFD0OKdKGBZdl1DZvOl2tVHw2XNcfbb0tce9Tixq7EvV43f9cfSzw8pPLoLldVtfZbWbWh9Z1euoY0G6vR+Vsm5V9AtVVroKROqFUAf6qrIaX8P9haGqjH5F8BbER4ldVFKLcDhRDQUV5FKU2Bdtqmn/G1K8UzsGlnAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n    >\n      <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\"\n        alt=\"book save\"\n        title=\"\"\n        src=\"/tech-blog/static/76b4dbe252c54a967e86da2e1dca52c6/fcda8/booksave.png\"\n        srcset=\"/tech-blog/static/76b4dbe252c54a967e86da2e1dca52c6/12f09/booksave.png 148w,\n/tech-blog/static/76b4dbe252c54a967e86da2e1dca52c6/e4a3f/booksave.png 295w,\n/tech-blog/static/76b4dbe252c54a967e86da2e1dca52c6/fcda8/booksave.png 590w,\n/tech-blog/static/76b4dbe252c54a967e86da2e1dca52c6/efc66/booksave.png 885w,\n/tech-blog/static/76b4dbe252c54a967e86da2e1dca52c6/c83ae/booksave.png 1180w,\n/tech-blog/static/76b4dbe252c54a967e86da2e1dca52c6/712f7/booksave.png 1181w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n    </span>\n  </span>\n  \n  </a>\n    </p>\n<p>Yaaaaaay !!!</p>\n<p>We got the response. Book saved.</p>\n<p>If we refresh the page, we will see the new book added.</p>\n<p>Oh My!\n\n  <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/tech-blog/static/c0b79d6c6053b409493c50740f6bd808/08a84/bookadded.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n  \n  <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 460px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 172.2972972972973%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAiCAYAAABfqvm9AAAACXBIWXMAABJ0AAASdAHeZh94AAADE0lEQVRIx+1US09TQRTuX3Bn4kKjhqioYQOy07gy+hMU2BAM8REXRg1G2KgLNMGFBnyAGxdGN0UgEgwBNUoVN1ig7/eLFqHt7fP23jufc6a9tWjBRtjJSb6cmTNnvjnnzJkxvJ6R0Tag4sJzFZ1DRZwfVNH+tIiOZ7/snUMKOgc1dLxIonXYglajFW1GG1q4bje6EFnNwND7RsbuK0DDTeBoF3DoOnDmPtAyAJzrB07cAepvFNeOdGlouArsejKFneGzOBi4jLrARRwOX8IOawfsqxEY+sbyOHCNoblHRVO3hsZuhuO3GU71Mpy+x3DyLkPjLYZjPQxN3KeZH1z/YBF7JvpQN96P/eOPsG/8IfaOPIb7xwoMwVgWiwEF7hjgiGiwBmVYggrm/UUs+AvcVuA2Xcuw+bifHbA6ORyAzQXYOSQpCwPTCgCT4Q94kIgvoyjcBqWEasJKWuZQoalp4ZvLcUJNY5jnx7w0jmH03RSkVAZ2hxMWqw0OpwuqqoG7gPw0raT5vKCocHu8UPj6l6+zPLoU8vk8DLIsQy4UkJQkpNMZvkEDY4wTqeVxNdAagURRFDHOZnmExPo3qSTQQTYSnZTmmQxvG5Wzr6zGMfVpBnMLFuEQj8d5ChISiYQY65t+F1qn6EKhECjTXC5Hl6LxG/JgYvoD3n82ibD9fj9cLpdw9Hq9YpMehS5kC4fDYmw2m0V0ooZ6yrpz5SZdKlPVa1uZ6pqU83lZGEiTc62ybg01TYU/FMbIxCQ+mmZFLQKBAGKxmNCEYDCISCQiSuDz+Xg3pAUJzSn1NSlTVKHIEr7NmfF90SoIk8lkGdFoVFyQfknLy8tiI+2juU5cvpRa2majlP+oITHTaeGlKBJJqWqNNurByosSjc2YBpvTjVfDo3g7OS3S8Xg8sNvtonXowGpCJNRSpE0mE1Kp0tMr8Gcn8QlFGOX1oSLTAoFqst7zIzvtJSE/Iq7p6VVLuTJ1vW1IZzLZYg2FoeL0f70kEaFOuN6vUgs2JNxM+2wTbhP+P4Rb9vQ2K2VC+su2Avof+hOElCTlSAvmWQAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n    >\n      <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\"\n        alt=\"book added\"\n        title=\"\"\n        src=\"/tech-blog/static/c0b79d6c6053b409493c50740f6bd808/08a84/bookadded.png\"\n        srcset=\"/tech-blog/static/c0b79d6c6053b409493c50740f6bd808/12f09/bookadded.png 148w,\n/tech-blog/static/c0b79d6c6053b409493c50740f6bd808/e4a3f/bookadded.png 295w,\n/tech-blog/static/c0b79d6c6053b409493c50740f6bd808/08a84/bookadded.png 460w\"\n        sizes=\"(max-width: 460px) 100vw, 460px\"\n      />\n    </span>\n  </span>\n  \n  </a>\n    </p>\n<p>That’s nice.</p>\n<p>However our experience could be better. We should clear the form, show some toast, and maybe dismiss the modal ?</p>\n<p>Lets add a spinner like</p>\n<p>\n  <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/tech-blog/static/50eddf146c4cd8e1cdc80277aa5c17e3/a4d88/loader.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n  \n  <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 495px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 163.51351351351354%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAhCAYAAADZPosTAAAACXBIWXMAABJ0AAASdAHeZh94AAADQElEQVRIx+2WW08TQRTH/SS++WBQQ0AhJkaNhgdjxK9iYqIiF0NQMSqgLz6IMaDxycTEGDAxSKEgtxi536QXWlraYqSUsp3Zndn5O7NTYIGWi8Q3T/LLObtz9r9nZ2fO7hHOTCSWKYYDBKNB4njF2DzB+D5RuVNhCkJMHAEoWrsoztQAlx4KlD3SnK0VKKkRKL23N8XVQFk9x68k0YLNHRRFVcDFB8DVp8C1Bjg3KLgNnKwATtyROF7oeP24Qo8fvwWcq7WxtJyRgraJgdkM6j9aaGyz8OSTpqndwjPFZ+bQ1GbiufLZ803tmznquhdfKFZWpSClFJxRAMKFMp7FyqJsPc/OmU9IVpAQKSpzNDohlUqjf2AI4xOTGBz6jh/DIxgdHUdf/yAmp2a0hMxVqEssxpHJZAUVbhNCIWBZFhhj4JxvxCpXeTWuc7VXOTsE1aCbvcydl1MwlUrB7/cjGo0iEAg48cLCAqanpzE7O+tUuV0or6C7IneVtm1vPK6Kc6Hycla4traGcDjsVBiJRODz+ZBIJLAfyyloWibS6bQjnJYkk0kYhpG3srwVmqYp1yJDOBTGgqwwIuctFJxHVFaZiMcRj8XyEMdidBHJ5WVHeIugmqORiVF0ej3w9HRJutHR3YmpuRkEwvPwhQI78IeCmAv6EFuK7xQ0uYVgOoZQJoFwZgkhI4F5Iw7/anRX5lIRxDK/twquzyG3GFaTKaRXVkEzBAexnMuGmgyG7GmG3IrEtGDK7WRaLhjfek7GVHrG1cvJufW27w6xTyBFXYKWRWFQgbe9Nlq8NloVPQKvuwWaPQKvPDpu8Qq8+ybkuOaNzHnZKdD3UzjdxjCkoOo0glPEkjYK7woUyOZ5SjZN5c/fB643AeWNsoHW6ePL9bqpKgorgaM3gOr3WjC95hKMJzlKaxiKKjlOVynPcKGOobyB4cpjJjuypkTmFMux4iodH7vJUPuBbwo6j2zKebQEeqcpuicpvFk8ExQdYxRfxym6JjTu8Z4pOTZGMLfInKZr5OuHf2NcvmmyZdm4OvBBUR0758Le3mD3i7JdBQ9i/wX/8Us5jG0Iqua6/vE+DOrLSIj8+1KB/h0hh0YV9weH+6hK2MfIJAAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n    >\n      <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\"\n        alt=\"loader\"\n        title=\"\"\n        src=\"/tech-blog/static/50eddf146c4cd8e1cdc80277aa5c17e3/a4d88/loader.png\"\n        srcset=\"/tech-blog/static/50eddf146c4cd8e1cdc80277aa5c17e3/12f09/loader.png 148w,\n/tech-blog/static/50eddf146c4cd8e1cdc80277aa5c17e3/e4a3f/loader.png 295w,\n/tech-blog/static/50eddf146c4cd8e1cdc80277aa5c17e3/a4d88/loader.png 495w\"\n        sizes=\"(max-width: 495px) 100vw, 495px\"\n      />\n    </span>\n  </span>\n  \n  </a>\n    </p>\n<p>and a toast like</p>\n<p>\n  <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/tech-blog/static/78ac45eb13aedaae29b842bfe97df7ba/7f664/saved.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n  \n  <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 456px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 169.59459459459458%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAiCAYAAABfqvm9AAAACXBIWXMAABJ0AAASdAHeZh94AAADNElEQVRIx62U20tUQRzH969xRXvINHOf0lV0S/HyJiz4oAhRFPUSQXeICOqlB3Ull0qi/gF9CFc0L3vRNQ0jXbXFIihMU3FvZ86Z821+czzruhddLwMffjO/+c33/Gbm/MYS+hXHjbcqrr02uOJWcVVY8uXLzX5jXa9HgcW3GIftMeB4DlwSOLuByy+As3fz59w9wHobuP6GwRIIxWB7pOHiEy6pfcZhf8pR/oDj/H3tAHiSCw85ztzhuNWfgGXtXxSTiwwTxALD2DeGcWF9Sxr8y1wSWOFyTNbwafCG2D4mFlXMr8ZhURIxZG8MuhqVcLYjxgq4sgOdRQAtxxpdbDkWi0HVdGhcxHFd9LmcC4dXMT4+iYXFEEY/jWHm8xyCM7Pw+vyYmg5CYSpEuFxDUD+RUAxBXdeNDwhrkvHxNF/6GmqKkiZ42IJs/ZyCxPr6uoQxljWrw1qGoKZpUFU1Zxa54JxnCpIzEokgHo+Lw01IS5nmK5pzy9vb29ja2sLm5iZoLp+t5xTMFkiZ50NWQcpsY2NDTpz4UugrdHYEXc5RssuZIQmZN22KnuhSaMtra2vSUqZHbfsENZG2WZcmVNf5Qkmmld5JSREkx9JvHb5lHVPfdQRMVgyfCY0DKfNTuzFkI+KEVDVFcHCW4+VHoGdYR7fHwCX6H3wG77063KN7c+n82RL3oDFTkGNwTpeCrmEShQgy+u8m93g1YvhpvsezF9eTKajjx18VX1YZvv5kmP8h2LXkM0n1E2Ys2bgiLpGx9PfwlC7F+A8hn/HjkePFPkplHFoppypIdUsFbtbycaD1KT/26TQSttBTHwqF4PV6EQgE4Pf7k/h8Pkm632R6ejpJMBiUb6nMsKOjAxUVFaiqqtqHw+GQVFZWwm63o7q6WvqpT7asrCxJSUkJRkZGYIlGo2hvb0d9fT1aW1vR1taGzs5ONDc3o6GhAS0tLairq0NjYyOampqkj+Yovry8PElpaSk8Ho8h6HQ6YbPZUFtbi5qaGilQVFSEgoICSWFhIaxWo2+1WpOWYoqLiyUUMzQ0ZJzhwMAgurq60NvbC5fLJenr64Pb7T4QijGhcTgcxn/NwH7XWLgyTwAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n    >\n      <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\"\n        alt=\"saved\"\n        title=\"\"\n        src=\"/tech-blog/static/78ac45eb13aedaae29b842bfe97df7ba/7f664/saved.png\"\n        srcset=\"/tech-blog/static/78ac45eb13aedaae29b842bfe97df7ba/12f09/saved.png 148w,\n/tech-blog/static/78ac45eb13aedaae29b842bfe97df7ba/e4a3f/saved.png 295w,\n/tech-blog/static/78ac45eb13aedaae29b842bfe97df7ba/7f664/saved.png 456w\"\n        sizes=\"(max-width: 456px) 100vw, 456px\"\n      />\n    </span>\n  </span>\n  \n  </a>\n    </p>\n<p>lets update our HTML</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\"> &lt;ion-button size=\"large\" [disabled]=\"addNewBookForm.invalid\" (click)=\"save()\" color=\"primary\" type=\"submit\"\n              expand=\"block\">SAVE ! &amp;nbsp;&lt;ion-spinner *ngIf=\"loading\">&lt;/ion-spinner>\n\n            &lt;/ion-button></code></pre></div>\n<p>And our TS file. all our logic is here.</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">  save() {\n    this.loading = true;\n\n    this.booksService.addNewBook(this.addNewBookForm.value).subscribe(\n      async data => {\n        console.log('got response from server', data);\n        const name = this.addNewBookForm.controls['name'].value;\n        const toast = await this.toastController.create({\n          message: `${name} has been saved successfully.`,\n          duration: 3500\n        });\n        toast.present();\n        this.loading = false;\n        this.addNewBookForm.reset();\n        //optional\n\n        this.modalCtrl.dismiss();\n      },\n      error => {\n        this.loading = false;\n        console.log('error', error);\n      }\n    );\n  }</code></pre></div>\n<p>This works great. We are redirected back to the page. However, there is one problem.</p>\n<p>Our list hasn’t been updated.</p>\n<p>So for that, we need to listen to event so when the modal gets dismissed, we know.</p>\n<p>lets update our modal code in books.page.ts</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">async openAddModal() {\n    const modal = await this.modalController.create({\n      component: AddnewbookComponent\n    });\n    modal.onDidDismiss().then(data => {\n      console.log('dismissed', data);\n      this.getAll();\n    });\n    await modal.present();\n  }\n}</code></pre></div>\n<p>Now that’s amazing.</p>\n<p>We’ve done quite a lot.</p>\n<p>2 more things we need to do to complete. Delete and Edit.</p>\n<p>Lets start with the delete functionality. We already have a delete button, we just need to add a confirmation popup and then delete.</p>\n<p>First, we don’t have the delete API method in Node.js. Lets create that.</p>\n<p>lets open our Node.js app and open books.controllers.js</p>\n<p>Surprise! There is already a delete method by the name of <code class=\"language-text\">deletebook</code>. I just made one change.</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">    const result = await Books.findOneAndDelete({</code></pre></div>\n<p>I capitalized Books. otherwise, it wouldn’t work. Here’s the complete method. <code class=\"language-text\">findOneAndDelete</code> is a mongoose (ORM) method that updates a single document / table in MongoDB.</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">booksController.deleteBook = async (req, res) => {\n  if (!req.params._id) {\n    Fu;\n    res.status(500).send({\n      message: 'ID missing'\n    });\n  }\n  try {\n    const _id = req.params._id;\n\n    const result = await Books.findOneAndDelete({\n      _id: _id\n    });\n\n    res.status(200).send({\n      code: 200,\n      message: 'Deleted Successfully'\n    });\n  } catch (error) {\n    console.log('error', error);\n    return res.status(500).send(error);\n  }\n};</code></pre></div>\n<p>To expose this method, lets open books.routes.ts</p>\n<p>Lets uncomment this line</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">router.delete(\"/:_id\", bookController.deleteBook);</code></pre></div>\n<p>Now, if we make a <code class=\"language-text\">delete</code> request to localhost:3000/books/12312313123</p>\n<p>then that user will be deleted.</p>\n<p>To do this in our Ionic app, we need to create a <code class=\"language-text\">delete</code>service method for books.</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">  public deleteBook(id: string): Observable&lt;any> {\n    const url = BookyConfig.getPath() + `/books/${id}`;\n\n    return this.http.delete(url);\n  }</code></pre></div>\n<p>Let update our HTML</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">  &lt;ion-button fill=\"clear\">\n          &lt;ion-icon name=\"create\" slot=\"end\">&lt;/ion-icon>\n        &lt;/ion-button>\n        &lt;ion-button fill=\"clear\" (click)=\"delete(book)\">\n          &lt;ion-icon name=\"trash\" slot=\"end\">&lt;/ion-icon>\n        &lt;/ion-button></code></pre></div>\n<p>Lets write code on that delete button</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\"> async delete(book) {\n    this.selectedBook = book;\n    const alert = await this.alertController.create({\n      header: 'Confirm!',\n      message: `Are you sure you want to delete the book \"${book.name}\"`,\n      buttons: [\n        {\n          text: 'Cancel',\n          role: 'cancel',\n          cssClass: 'secondary',\n          handler: blah => {\n            console.log('Confirm Cancel: blah');\n          }\n        },\n        {\n          text: 'Okay',\n          handler: () => {\n            this.deleteBook();\n          }\n        }\n      ]\n    });\n    await alert.present();\n  }\n\n  deleteBook() {\n    this.deleteLoading = true;\n    this.booksService.deleteBook(this.selectedBook._id).subscribe(\n      data => {\n        console.log('got response from server', data);\n        this.deleteLoading = false;\n        this.getAll();\n      },\n      error => {\n        this.deleteLoading = false;\n        console.log('error', error);\n      }\n    );\n  }</code></pre></div>\n<p>\n  <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/tech-blog/static/9136b5aef95ab19970f45c3bd0f9d6b5/50978/deleteconfirm.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n  \n  <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 478px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 170.27027027027026%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAiCAYAAABfqvm9AAAACXBIWXMAABJ0AAASdAHeZh94AAAFW0lEQVRIx6VWSWwbZRTOjQN3BFRCAu4UFU5AKyrUCiTUqhInDlyghRsUECohrWiatAlZnaTxbsfLjGexncZpdocW6rRKEWoWp656qWiqCnV19qWxP977Z8aehIYeGOnTm/n9z+e3/d+bivX1dSwureBRfhGP5wimFc/WmrVuW8s/WkP+4XoJjx+sY2lxDRVAEaG+HN450ouPjg5i/9cDAh8eNew+E/u3YM9JF3bXNWH3mRbsrXfgzRN1UDJ/GoSN0gSe/0DCK4fi2HFQx0sHdOz6TMfuwwZe/8RY23FQE7+/fEDDc6cO4UXfXrzg3IfXvB+jovltNIwpBqG3ewI7P5Ww96ukIHj3Cw17Dmt4/wjhS43WNFrT8R6tC3yu463va/HGTz9gZ+WP2FVViVe/+RbhXzOoKBaLuHZtEqGwBH9XBOFoDIqqQ9ESUPUkYmpc3McUfRMU+Rw0KQWVoMd6Ee1KYHoqh4pCoYCZmSzaOjpwrOoEauvqoakKzp7tgMvlhMvZCa/Xg2QygWQiUbLd3XFI9MeypsMXjcMbknHjxozh4dTUFHz+AFweLzw+PzSdvIjFIEkyFEUljxTE4/F/QdPj0OMJsklEZYUcMwknJyehaRr6zp9HKtWDhPCgWyCZTArwmh1MmDDRTV4rSgxZi3B6ehqBYBC/NLWg0+UWmyVJgizLAuxtNBo1vZYEDA8pz1qc8pxEhHJ//fqMmcNsFi2ONlT9XI0ayiG/6Ha7EQgE4HQ60dnZCb/fD5/PR3l1iWddUyEpVCw1gUAkCV+Xghs5W8jsiT0kK9TtIEJOGOBCxWLy5hwqlHiJSMPhcCksCxzuVth/j+saFIpKEHLIWQq5udWB6jP11HM6RkdHMTAwgL6+PmFHRkaQTqeFtZBOj2BomO7TowjHeuD2R5GzQmbChsYmXMqMga/l5WUsLS1hcXERGxsbeNZ16fIfVEwvEV4vh+yhIkxOTGB1dVVUPZfLCZvP58VLvG+768qVMbjpEJRyyI3d0tKKCxcvig1ra2vCM04Hyxs/s11ZWRFes52fnxf3fP32e4ZOlpPahjwsECEzV1Ydx7lUryC6desWbt++jTt37gjLz7Ozs7h7967wmMnu3buH+/cfCMLUUAYNLZ3UNraQ29raMD4+LjbMzc0JsAcLCwuC5DHhyZMnTw05k8mI3tzUNtzAV69exbOvoplPRkGsjI1dgtNOyFWuqT2N3r5+scHKH6NYLGCD7N/5AmYfFPFwwSBj+9d9g3AwnUGzw1muMhNW19SKvtruWl4HaGRg1eyiNbLzK8Z9+sJltLbbCCeoXYIkDiqdFlVVEY5ExImxQ4oaiEaNZ7YywRCMCL0fEI6VchgKhdDqcKCpqRkdJLbt7e2iUBYcjjKsZ7a8NxjsQoScKB29GfPofXesEsdPnhLnkzc3NjYKxWGv2RM7VDWGYFihkaHAFdThDshlteHG7iIPg10hsmEhtiwWDL5/mlqXFNtUbdkSB7ti96ZS6Ok5t0mxGfyyTmOhbHVhE3HjXig2yVc2a1NsL82SGlIbR3uHIOScMrhY7Kkl+xZYB1mtFUJUSSIUUcqKzdVhourTdagj1eGc+Xw0sDwe0fCc07KoMrEx/SzFDkpJ+ENKWb4sgbWGEr9oV+et3pW8NK01pDbl0KieUQT7CNiOzD4CNhEag34GrW3tom1O1p4RCechxQeeB9PWESqKZoYsU8j+pw0pj5cmmtsjLIcfMU8Lzw/+A/bcDp3niKpRvjXI9GkSikjiC0QQsjqfpyE/MjyM4aEhMUcYg4ODwvb39/8nBmkPfyDcvHkTFazEPENY9/4vWMn/AehZd2yauC2UAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n    >\n      <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\"\n        alt=\"deleteconfirm\"\n        title=\"\"\n        src=\"/tech-blog/static/9136b5aef95ab19970f45c3bd0f9d6b5/50978/deleteconfirm.png\"\n        srcset=\"/tech-blog/static/9136b5aef95ab19970f45c3bd0f9d6b5/12f09/deleteconfirm.png 148w,\n/tech-blog/static/9136b5aef95ab19970f45c3bd0f9d6b5/e4a3f/deleteconfirm.png 295w,\n/tech-blog/static/9136b5aef95ab19970f45c3bd0f9d6b5/50978/deleteconfirm.png 478w\"\n        sizes=\"(max-width: 478px) 100vw, 478px\"\n      />\n    </span>\n  </span>\n  \n  </a>\n    </p>\n<p>Yesssss. Our delete functionality is working.</p>\n<p>\n  <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/tech-blog/static/c9b165fbaa83c0fa78fd61b9d55125ae/69096/deleteworks.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n  \n  <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 464px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 111.48648648648648%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAWCAYAAADAQbwGAAAACXBIWXMAABJ0AAASdAHeZh94AAADBUlEQVQ4y6VT22oTURTNN4jPRRGxgtYLfRRffBH/QATffCr4okjtBbXWFioIIhW/wdZrlbSmranWCgVDLzE1aUNMSy6TS1OTTOZ6znKfMzMxram0eGCx55w9s2bvtdfxbeR0TC7p+BgmLDtR7D8s6Agsujk6n152Y1hDcMnCdIhjMmRLBL7ZmFngKFcM+Ea/6jh+C2jvBc72AKe7gXN9wMUh4MKg8yzORO5ML0N7J9D6KIaWuSG0fn6KY7PDEoeCT7Ca24Tv+ZyGIzeAti6Ok7chyc/3A1efAZeHgUsPnbM2yp3oYjh1E2h5PI+Da1dwNHodh6MdOLLagQPL1/Ajl4NvPlbD3VETg28sDLwWMNH3wsCdEYPODdx/acqzBy4GXtnof1tBz3gcXf44uil2+tdwbyKJTLEKn21qcJZFsAkc25fYsx1ovjStBp9pWlDymxgZG8e7QBAVVUPi5zriiSQSyQ0Ypg2bOCyC7cJiHDZnUMoMqsmwpjBoFGs1SWiiuFlCeCWKSHQVVVVFpVxGsViUYMypiHP+V0WqTvVSmjqlH3GHUNM0/GsJwt0g2ufciYzZDqGu6zKZymSRyxckiW3bdTKvMhEbATcy5sFt2bYspLMKRsf8GJuYInNWkEgkEIlEZIxGo1BJhsa2veazW4BBs4ykANPizlAM3SBmDVnykEIVGqSp+ERoKyr12ttZoazOjWJQbK8aNltOq8RC+nFXS/FzSWgYVCGRzocWsfh9RSYq1Ha1Wq3HMk1dQOxF9IrQTA7L5tiqNUxZaCgG4p8KIjAzi1/0QTqdlkilUojFYshkMnKfTCalrjmSR8iSL5N2NL+4AkmseS2L8kVlAs381tRO8j134miYsle+JGNszxry3Qgt96a8D0xj8tMX6KRpPk8TVxSKedmueBaIx+Nyb0onACWVS9usFxpaFslCcROhpTAWwhGodCgGUSgUUCqVpF6CzHsWP/GMX9aEdYBcWXT4H7apXz3+5wrWbSMIm5l2f2hi7G33dJ8m9+KuhPtFI+FvQvZtsLdG7ScAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n    >\n      <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\"\n        alt=\"deleteworks\"\n        title=\"\"\n        src=\"/tech-blog/static/c9b165fbaa83c0fa78fd61b9d55125ae/69096/deleteworks.png\"\n        srcset=\"/tech-blog/static/c9b165fbaa83c0fa78fd61b9d55125ae/12f09/deleteworks.png 148w,\n/tech-blog/static/c9b165fbaa83c0fa78fd61b9d55125ae/e4a3f/deleteworks.png 295w,\n/tech-blog/static/c9b165fbaa83c0fa78fd61b9d55125ae/69096/deleteworks.png 464w\"\n        sizes=\"(max-width: 464px) 100vw, 464px\"\n      />\n    </span>\n  </span>\n  \n  </a>\n    </p>\n<p>Great. So One last thing. Edit.</p>\n<p>For edit, we will use that component we created already.</p>\n<p>Lets edit the html and add a function</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">    &lt;ion-button (click)=\"openEditPopup(book)\" fill=\"clear\">\n          &lt;ion-icon name=\"create\" slot=\"end\">&lt;/ion-icon>\n        &lt;/ion-button></code></pre></div>\n<p>Now lets add some functionality.</p>\n<p>We will be doing a little bit of magic. We will use how we can reuse functions. I will use 1 function for 2 scenarios.</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">openEditPopup(book: Books) {\n    this.openAddModal(book);\n  }\n\n  async openAddModal(book?: Books) {\n    const modal = await this.modalController.create({\n      component: AddnewbookComponent,\n      componentProps: { book }\n    });\n    modal.onDidDismiss().then(data => {\n      console.log('dismissed', data);\n      this.getAll();\n    });\n    await modal.present();\n  }</code></pre></div>\n<p>This saves me writing a lot of code. I just open the modal using same function.</p>\n<p>I pass ‘book’ as optional parameter.</p>\n<p><code class=\"language-text\">componentProps</code> help us send data to that component. We can access there using @Input() book.</p>\n<p>after the popup opens, we need to patch the data to our form.</p>\n<p>updated addnewbook.component.ts</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\"> @Input() book;\n  ngOnInit() {\n    this.formInitializer();\n    if (this.book) {\n      console.log('got book', this.book);\n      this.addNewBookForm.patchValue(this.book);\n    }\n  }\n\n  formInitializer() {\n    this.addNewBookForm = this.formBuilder.group({\n      _id: [null],\n      name: [null, [Validators.required]],\n      ibn: [null, [Validators.required]],\n      author: [null, [Validators.required]],\n      is_deleted: [false, [Validators.required]],\n      image_url: ['']\n    });\n  }</code></pre></div>\n<p>I added a _id field. its not required.</p>\n<p>Every record created in MongoDB has a unique <code class=\"language-text\">_id</code>.</p>\n<p>The best thing is there is no need of sequence like in Mysql or Postgresql. MongoDB manages unique IDs itself.</p>\n<p>We will use that ID.</p>\n<p>\n  <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/tech-blog/static/bce2089c3e3f3149604a9ce0f1794a44/d743b/clickonedit.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n  \n  <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 477px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 168.24324324324326%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAiCAYAAABfqvm9AAAACXBIWXMAABJ0AAASdAHeZh94AAACzElEQVRIx+1VS09TQRTuTzEuiUhioiKRmPiIxsSN0a1xp2FjdAOCUIJG0MSFbmABPpb42OjOlTsTQV4RKmmhSAHbBijPO/fO3JnPOXN7od5b6cVuXHiSr+d0Ht+cx8y5Mc4d5As25rIM8zlmtG/P56Mho/FDry9s2IgBDG2DHMfiwJluhXM9Hk49UDjZpdB4vzJo7ZF7Ci8/FQlvveKo7wROdwOXnwKXnsD8r2kGDt3VaNkbda3AgdtA70cidBn6tHGt10XTc4Eb/R5uDmg9wI02dj/f0b7to+mFwPU+gQ9DFmKWxaBcG4AbgERYVInthiAchhhjDI7DzVKpf2SRZ219A2PjE/g2OYXRsXEkEtNIfJ/GyOgYJqcScLjY3VMEY7ZHyDn3zldKE0qtoQ9xkMvlsLKyguXlZWSzWayurmJpacmMy+LJtIdAYtsBwv2KTxYipJBJyJNMJoPFxUVYlhXaFCQISsjDzc1N5PN5E1JpGqKgLKHrumaQ8kceEmhuN7cRCYnAVHZtDclkErOzs0ilUkaT176nlSRyUci7SihLWCgUsLCwYK5GOp02NqUhSi7LElLOiJRCp/tHdqXc7UkohAiF7xdkXyH7RSGvKEyTN//0Mq84+Lr9ev3mIQ26LnmjIFy5b9D+XQ93wlRVQDcHItzW7QuKI51XaB2U6HwnES9B+xuJtteejgfmaG37W4me9xIblo6Ma8KtbU0Ijs9JiYN3gMOtXpeu1ahp8br31WfAFY2GLt2d27wuXeuvaaburvCzoPMtSgiHZ1zUtXA0dArUxz0c7xA43yNw8bHAhUcCjV0CJ2iuw5sn+2i7wNmHHLl1XW0ipI7tCo4tJjGcYhidsTFSgqGkjS9JT38NzBFobGLOBtcFdYLtq1phoW6jr8zfouxLidr7Ij+9KC3qT5+B/4T/UFH2/KZU4yHBEFJzJVL/s1kNiOcXkb3+xDopkSIAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n    >\n      <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\"\n        alt=\"clickonedit\"\n        title=\"\"\n        src=\"/tech-blog/static/bce2089c3e3f3149604a9ce0f1794a44/d743b/clickonedit.png\"\n        srcset=\"/tech-blog/static/bce2089c3e3f3149604a9ce0f1794a44/12f09/clickonedit.png 148w,\n/tech-blog/static/bce2089c3e3f3149604a9ce0f1794a44/e4a3f/clickonedit.png 295w,\n/tech-blog/static/bce2089c3e3f3149604a9ce0f1794a44/d743b/clickonedit.png 477w\"\n        sizes=\"(max-width: 477px) 100vw, 477px\"\n      />\n    </span>\n  </span>\n  \n  </a>\n    </p>\n<p>Click on edit button now opens that book with its data. that’s amazing.</p>\n<p>Although I see <code class=\"language-text\">Add New Book</code> here which is wrong.</p>\n<p>Also clicking on Save would not work because we are calling ADD api when we should be calling EDIT api.</p>\n<p>We will change that.</p>\n<p>First we update the text at the top.</p>\n<p>we know that in edit case, <code class=\"language-text\">this.books</code> exists.</p>\n<p>we will use that.</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">     &lt;div class=\"ion-text-center\">\n            &lt;h3 *ngIf=\"!book\">Add New Book&lt;/h3>\n            &lt;h3 *ngIf=\"book\">Edit Book&lt;/h3>\n          &lt;/div></code></pre></div>\n<p>\n  <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/tech-blog/static/0e15d1c291a72bfd64e11dbb407a4793/a9b70/edit.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n  \n  <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 479px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 116.21621621621622%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAXCAYAAAALHW+jAAAACXBIWXMAABJ0AAASdAHeZh94AAACiElEQVQ4y6WUTWtTQRSG809cuVAjShUEwUoWUpR2qT9DXNTWakWktdRicaFFaQUXpv0DglJr40Ja/KzWbhpq6SJw82FMTZrMvbkf83rOTG5zc5MmEQceztwz57x35gxzIhXTwsqmhTffLbz9oe3SuoXERne829B5q6QhSCvya9fExSkXZ+4A58aAC5NA7zhw4mZ3nLwFHBkCLpHG7z8CkRwJ9t13cfYucJ6EBqaB2AQQvQEc8xkOzEMcHwEODwJ9ky7yLFjcE4i/t/B40cbTJRszZJ+QnV22MZdwFM8SrrLsCzO3rOPnSYO1IqYpADiEJLyQtQmLMGtz9ru1NRmKdWAKEhTCRNV24ZLfoViHrO1yAGBkclhZ/YDPX74Ra/j46Ssyubxa4xinlsO5rCF8Qdd14Q8ppYIH+y3LguM4qFarCs/zGuKCsU2C/mJ4Hh5BsRaCYl9we3sbyWRS2XBSMLnVaBLkYLZ8vHAJ+Jjt8HObdpjP55HJZJBOp2EYhprzD1ods6sjF4tFFAoFJczwPFjffxI8qE7/deRUKqUuZGdnR11ONpvteONtL8VP5m+m08467jCXy6FUKjXsql3tOtQQdAm7KFcEPMlPyiM/Iw/GkyqmYYem6b+UYJ28UANoh36KjhN4etKj5rgHJA0PPzNyny1i05Dk12wF/H4M+wtlKA0lWK6YqiXNLLk4NSoRuyep0Ur0jun5wLRE/wNNbEL71fq4Xu+hnNmEbmtcrn3BqZceDl3TbT1KXfgodenTt4Erj4DLRD918p5R3aWjNTiWcx6+rgmWSbBSEerj1VoVV58LjCwIDM/XGXyhuR4XGIo3rnEs5yyu2/UdcseuN4Ngx+6G5kv5C3O2nDXEPVHQAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n    >\n      <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\"\n        alt=\"edit\"\n        title=\"\"\n        src=\"/tech-blog/static/0e15d1c291a72bfd64e11dbb407a4793/a9b70/edit.png\"\n        srcset=\"/tech-blog/static/0e15d1c291a72bfd64e11dbb407a4793/12f09/edit.png 148w,\n/tech-blog/static/0e15d1c291a72bfd64e11dbb407a4793/e4a3f/edit.png 295w,\n/tech-blog/static/0e15d1c291a72bfd64e11dbb407a4793/a9b70/edit.png 479w\"\n        sizes=\"(max-width: 479px) 100vw, 479px\"\n      />\n    </span>\n  </span>\n  \n  </a>\n    </p>\n<p>This was so simple. All we needed was very little logic</p>\n<p>Lets update our Edit and Add button.</p>\n<p>Here is how our save() function looks like</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">  save() {\n    this.loading = true;\n\n    if(this.book){\n      this.updateBook();\n    }\n    else{\n      this.addNew();\n    }\n\n\n  }</code></pre></div>\n<p>and those two functions</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">  addNew(){\n  this.booksService.addNewBook(this.addNewBookForm.value).subscribe(\n    async data => {\n      console.log('got response from server', data);\n      const name = this.addNewBookForm.controls['name'].value;\n      const toast = await this.toastController.create({\n        message: `${name} has been added successfully.`,\n        duration: 3500\n      });\n      toast.present();\n      this.loading = false;\n      this.addNewBookForm.reset();\n      //optional\n\n      this.modalCtrl.dismiss();\n    },\n    error => {\n      this.loading = false;\n      console.log('error', error);\n    }\n  );\n}\nupdateBook(){\n  this.booksService.updateBook(this.addNewBookForm.value).subscribe(\n    async data => {\n      console.log('got response from server', data);\n      const name = this.addNewBookForm.controls['name'].value;\n      const toast = await this.toastController.create({\n        message: `${name} has been updated successfully.`,\n        duration: 3500\n      });\n      toast.present();\n      this.loading = false;\n      this.addNewBookForm.reset();\n      //optional\n\n      this.modalCtrl.dismiss();\n    },\n    error => {\n      this.loading = false;\n      console.log('error', error);\n    }\n  );\n}</code></pre></div>\n<p>This is great. We still need to create that Update function in our service. Before that, lets see if its added in our Node.js app.</p>\n<p>add this line to books.routes.js</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">  router.put(\"/:_id\", bookController.updateBook);</code></pre></div>\n<p>books.controllers.js</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">booksController.updateBook = async (req, res) => {\nif (!req.params.\\_id) {\nres.status(500).send({\nmessage: 'ID missing'\n});\n}\ntry {\nconst \\_id = req.params.\\_id;\nlet updates = req.body;\nrunUpdate(\\_id, updates, res);\n} catch (error) {\nconsole.log('error', error);\nreturn res.status(500).send(error);\n}\n};\n\nasync function runUpdate(\\_id, updates, res) {\ntry {\nconst result = await Books.updateOne(\n{\n\\_id: \\_id\n},\n{\n\\$set: updates\n},\n{\nupsert: true,\nrunValidators: true\n}\n);\n\n    {\n      if (result.nModified == 1) {\n        res.status(200).send({\n          code: 200,\n          message: 'Updated Successfully'\n        });\n      } else if (result.upserted) {\n        res.status(200).send({\n          code: 200,\n          message: 'Created Successfully'\n        });\n      } else {\n        res.status(422).send({\n          code: 422,\n          message: 'Unprocessible Entity'\n        });\n      }\n    }\n\n} catch (error) {\nconsole.log('error', error);\nreturn res.status(500).send(error);\n}\n}</code></pre></div>\n<p>Great.</p>\n<p>Lets add the service method.</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">public updateBook(data: object): Observable&lt;any> {\nconst url = BookyConfig.getPath() + `/books/${id}`;\n\n    return this.http.put(url, data);\n\n}</code></pre></div>\n<p>I think this should work.</p>\n<p>\n  <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/tech-blog/static/8298b265aa16aad285283c6da9b001e7/f7a31/yess.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n  \n  <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 458px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 175%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAjCAYAAACU9ioYAAAACXBIWXMAABJ0AAASdAHeZh94AAADS0lEQVRIx+1VSU8UQRSeH2C8e/FgQkxEkIPLSU8m3vwFmuiRqAkmCEJQDy7Riwe9uJ1MjEhISERIiCwymIBLREBEBIZZgWGYoadnptfp+nyvumfYRJZw8EAlX15XVfdX733vvWpfNGGg54cB/6iB3lHXfqB517CB7hF3r3d0OXT4f5jwDznoHrLQM2S79nseMwkLvpZPBsrqgBO3BI7dFDh6Q+DkbYEzDwRO3xc4dcddd+HgeANQcS+J/d2PUep/joO9T1De9wL7uh6haeI3fM39OkqqgSP1QDnhUC2IELjwFLj4DDj7ECitdffK6h1U1AAldyPYO3Yeh6eqcGCiEuVTV7Fn7BxehgbgG/ilofqViYYmC/VvCI0Wrr82cY3Wagj8XNdIIFvfyLBR15RDVdtPXHo3jCttI7jcNozKtyP4NJWCzzJ1uCPvYaPhrLtjGSYRWhZSior2rl509fUjpxmIxmYwHQwhGApjPrGA+HwCoXAEaibrHu0ICCJO5RzotoNIyoGiOzDJOUm4kExh4OsgPg8OyY/S6TTm5uYkksmknMfjcWiaJgmFENJmdCYHkhlAMwHTIEJd17GV4TiOJGTL4QvheDIIaHqBkF5YVNJIq5kNiZaDSRzP8py5fHnbRpx0am5tR2tHpySNhMMYHx9HNBrF5OQkVFVdEapnsEDnGzYQmAcWc4DNGpqmiUw2iylKQoCSoBsGeE1RFHliLpcD61wgXPKONLNdcp22bSoQYysarg5Xakj6CU9LftY0IjTII5vCHp8MSA/5RfawAN5jGJ7nhTXWjcuHYdquNQoazszF0dLegbb33TI5MdJuenoasVhMahkmTYPBoFxjTUN0MBMmVDfsooaW5yFrpFCtKWmVTs8XQ2Kbz+dXlEoRci6kiGyLWd5qHS4vo0K5sC3WIWuSow7oG/iCz9++S28zVCac5WzW7ZqC5a5huBpydwhYlF2FwjUsr1N4czY+j44ePzr9H7Hofcg1ODs7K7WLRCJyzs+BQKDYgqmskOUSSQIqLfFFs62Q/956zlLrLXWAWCv+OhBeMopYnZTlHbDdsS7h6q7YDP5JuFU9dwl3Cf97wu1iDeFOjCLhZm6XzUAS8j+FL8ydAHP9AWTkcT2T3nnKAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n    >\n      <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\"\n        alt=\"yess\"\n        title=\"\"\n        src=\"/tech-blog/static/8298b265aa16aad285283c6da9b001e7/f7a31/yess.png\"\n        srcset=\"/tech-blog/static/8298b265aa16aad285283c6da9b001e7/12f09/yess.png 148w,\n/tech-blog/static/8298b265aa16aad285283c6da9b001e7/e4a3f/yess.png 295w,\n/tech-blog/static/8298b265aa16aad285283c6da9b001e7/f7a31/yess.png 458w\"\n        sizes=\"(max-width: 458px) 100vw, 458px\"\n      />\n    </span>\n  </span>\n  \n  </a>\n    </p>\n<p>Yesssssss. We finally did it.</p>\n<p>We completed the whole Books API.</p>\n<p>This post was alot of work but we eventually did it.</p>\n<p>We covered a lot of things but were finally able to complete the API.</p>\n<p>Here’s <a href=\"https://github.com/alamgirqazi/intro-to-nodejs-part6\">link</a> to the node.js app code.</p>\n<p>Here’s <a href=\"https://github.com/alamgirqazi/booky-ionic/tree/part6\">link</a> to the ionic app code. (<em>branch part6</em>)</p>\n<p>In the next part, we will cover Guards and Authentication. Only the user who logged in should see the books list and should only be able to add/edit/delete. We will discuss concepts like Authentication, Authorization, Guards and Interceptors.</p>\n<p>In part 8, we will deploy our App.</p>\n<p>We will deploy our MongoDB Database to mlab / MongoDB Atlas</p>\n<p>we will deploy our Node.js app to Heroku. There are also other platforms like Now.sh, Digital Occean, AWS Cloud, Google Cloud.</p>","frontmatter":{"title":"A very basic introduction to Node.js - Part 6","date":"December 12, 2019"}}},"pageContext":{"slug":"/intro-to-nodejs-part-6/","previous":{"fields":{"slug":"/intro-to-nodejs-part-5/"},"frontmatter":{"title":"A very basic introduction to Node.js - Part 5"}},"next":{"fields":{"slug":"/intro-to-nodejs-part-7/"},"frontmatter":{"title":"A very basic introduction to Node.js - Part 7"}}}},"staticQueryHashes":[]}