{"id":1315,"date":"2016-08-18T15:32:02","date_gmt":"2016-08-18T15:32:02","guid":{"rendered":"https:\/\/ionic.io\/blog\/?p=1315"},"modified":"2016-09-01T05:44:12","modified_gmt":"2016-09-01T05:44:12","slug":"one-mean-ionic-2-todo-app-on-heroku-part-2","status":"publish","type":"post","link":"https:\/\/ionic.io\/blog\/one-mean-ionic-2-todo-app-on-heroku-part-2","title":{"rendered":"One MEAN Ionic 2 Todo App on Heroku, Part 2"},"content":{"rendered":"<p>In <a href=\"https:\/\/ionic.io\/blog\/one-mean-ionic-2-todo-app-on-heroku-part-1\/\">part 1 of this series<\/a>, we started building an end-to-end Ionic 2 app with a Node.js backend. If you\u2019re just joining us now, you\u2019ll probably want to stop and go back to the first post.<\/p>\n<p>Up to this point, we\u2019ve worked primarily in the <code>server.js<\/code> file where we created an Express app and defined the api endpoints for the todos stored in a MongoDB database, provisioned by mLab via Heroku.<\/p>\n<p>In this next post, we\u2019ll write Angular 2 code using TypeScript to create the frame for our Ionic 2 todo app, communicate with our backend and display the todo that we added to the database.<\/p>\n<p>Sound good? Great, let\u2019s get going.<\/p>\n<p><!--more--><\/p>\n<h3>Display all of the todos<\/h3>\n<p>Now that our backend server and database are super-hardcore, we can start building out the frontend todo app. Out of the box, when the Ionic CLI created our project, the app folder looks like this:<\/p>\n<p><a href=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2016\/08\/app-folder.png\"><img loading=\"lazy\" decoding=\"async\" width=\"166\" height=\"179\" class=\"size-full wp-image-1381 aligncenter lazyload\" data-src=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2016\/08\/app-folder.png\" alt=\"app folder\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" style=\"--smush-placeholder-width: 166px; --smush-placeholder-aspect-ratio: 166\/179;\" \/><noscript><img loading=\"lazy\" decoding=\"async\" width=\"166\" height=\"179\" class=\"size-full wp-image-1381 aligncenter\" src=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2016\/08\/app-folder.png\" alt=\"app folder\" \/><\/noscript><\/a><\/p>\n<p>From here, let\u2019s start adding the pieces to display our todos.<\/p>\n<h3>The Todo Object<\/h3>\n<p>All of the todo data that will be sent from our API will be in a JSON format that we stealthily defined in the last post when we added a todo. If we specify what that data will look like as an object, we\u2019ll be able to take advantage of strong typing (type checking) in TypeScript to ensure each <code>Todo<\/code> has the correct properties. In order to do this, create a file in your <code>app\/<\/code> folder called <code>todo.ts<\/code> and put the following code:<\/p>\n<pre><code class=\"javascript\">  \/\/todo.ts\n  export class Todo {\n    _id: number;\n    description: string;\n    isComplete: boolean;\n  }\n<\/code><\/pre>\n<p>We\u2019ll use this object in other files shortly.<\/p>\n<h3>The TodoService<\/h3>\n<p>In our Angular 2 app, we want to abstract HTTP services away from our view logic. In Angular we do this by creating a service, also known as a provider. We can use the Ionic CLI to generate a new provider:<\/p>\n<pre><code>  $\/todo-ionic2-heroku &gt; ionic g provider TodoService\n<\/code><\/pre>\n<p>The <code>ionic g<\/code> command just created <code>\/app\/providers\/todo-service\/todo-service.ts<\/code> for us. If you go into this new file, you\u2019ll see it generated a <code>load() { \u2026 }<\/code> function for us. Let\u2019s update this file to get our todos:<\/p>\n<pre><code class=\"javascript\">  \/\/todo-service.ts\n  import {Injectable} from &#039;@angular\/core&#039;;\n  import {Http, Headers} from &#039;@angular\/http&#039;;\n  import {Observable} from &#039;rxjs\/Observable&#039;;\n  import &#039;rxjs\/Rx&#039;;\n  import {Todo} from &#039;..\/..\/todo.ts&#039;;\n\n  @Injectable()\n  export class TodoService {\n    todosUrl = &quot;\/api\/todos&quot;\n\n    constructor(public http: Http) {}\n\n    \/\/ Get all todos\n    load(): Observable&lt;Todo[]&gt; {\n      return this.http.get(this.todosUrl)\n                 .map(res =&gt; res.json())\n                 .catch(this.handleError);\n    }\n\n    handleError(error) {\n      console.error(error);\n      return Observable.throw(error.json().error || &#039;Server error&#039;);\n    }\n  }\n<\/code><\/pre>\n<p>Our <code>load<\/code> function uses the HTTP module from Angular 2, made available as a class variable in our <code>TodoService<\/code>\u2019s constructor. For <code>http.get<\/code>, we\u2019ll get an Observable back with JSON data. We\u2019ll <code>subscribe<\/code> to that data in our Component class in the next section.<\/p>\n<p>Note that we updated our <code>import<\/code> statements to include <a href=\"https:\/\/angular.io\/docs\/ts\/latest\/guide\/server-communication.html#!#rxjs\">Observables<\/a>, which we\u2019ll use instead of built-in ES6 Promises. Just know that you could have just as easily worked with <a href=\"https:\/\/angular.io\/docs\/ts\/latest\/guide\/server-communication.html#!#promises\">Promises<\/a> instead. We also included the <code>Todo<\/code> class to allow for type checking and HTTP <code>headers<\/code> which we\u2019ll use in our other HTTP methods that we\u2019ll add in the next post.<\/p>\n<p>For now, let\u2019s go ahead and update our <code>app\/pages\/home\/home.ts<\/code> file to <code>load()<\/code> the Todo list using our awesome TodoService class.<\/p>\n<h3>The HomePage Component<\/h3>\n<p>Head into your <code>home.ts<\/code> file found in <code>\/app\/pages\/home\/<\/code> and start by importing the TodoService:<\/p>\n<pre><code class=\"javascript\">  import {TodoService} from &#039;..\/..\/providers\/todo-service\/todo-service&#039;;\n<\/code><\/pre>\n<p>Then we update our <code>@Component<\/code> decorator with metadata specifying our TodoService as a provider:<\/p>\n<pre><code class=\"javascript\">  @Component({\n    templateUrl: &#039;build\/pages\/home\/home.html&#039;,\n    providers: [TodoService]\n  })\n<\/code><\/pre>\n<p>Now, we can update our empty constructor, create a todos property, import the <code>TodoService<\/code>, and assign it to a property of the class.<\/p>\n<pre><code class=\"javascript\">  public todos: Todo[];\n\n  constructor(public todoService: TodoService) {\n    this.loadTodos();\n  }\n<\/code><\/pre>\n<p>With our <code>TodoService<\/code> ready to roll, let\u2019s add a <code>loadTodos<\/code> method to use our <code>TodoService<\/code> where we\u2019ll <code>subscribe<\/code> to the <code>Observable&amp;lt;Todo[]&amp;gt;<\/code> returned by our HTTP request and extract our todos into our class\u2019 todos parameter:<\/p>\n<pre><code class=\"javascript\">  loadTodos() {\n    this.todoService.load()\n        .subscribe(data =&gt; {\n          this.todos = data;\n        })\n  }\n<\/code><\/pre>\n<p>If you don\u2019t subscribe to the Observable returned by the methods in our `TodoService, that \u201cobservable is <a href=\"https:\/\/github.com\/Reactive-Extensions\/RxJS\/blob\/master\/doc\/gettingstarted\/creating.md#cold-vs-hot-observables\">cold<\/a>. This\u00a0means the request won&#8217;t go out until something subscribes to the Observable&#8221; (<a href=\"https:\/\/angular.io\/docs\/ts\/latest\/guide\/server-communication.html\">Angular 2 Docs<\/a>).<\/p>\n<p>Put this all together and we have the <code>home.ts<\/code> file below (which also includes an additional import statement to include the <a href=\"http:\/\/ionicframework.com\/docs\/v2\/api\/components\/item\/ItemSliding\/\">Item Sliding component<\/a>).<\/p>\n<pre><code class=\"javascript\">  \/\/home.ts\n  import {Component} from &quot;@angular\/core&quot;;\n  import {ItemSliding, Item} from &#039;ionic-angular&#039;;\n  import {TodoService} from &#039;..\/..\/providers\/todo-service\/todo-service&#039;;\n  import {Todo} from &#039;..\/..\/todo.ts&#039;;\n\n  @Component({\n    templateUrl: &#039;build\/pages\/home\/home.html&#039;,\n    providers: [TodoService]\n  })\n  export class HomePage {\n  public todos: Todo[];\n\n  constructor(public todoService: TodoService) {\n    this.loadTodos();\n  }\n\n  loadTodos() {\n    this.todoService.load()\n        .subscribe(data =&gt; {\n          this.todos = data;\n        })\n    }\n  }\n<\/code><\/pre>\n<h3>The HomePage Component\u2019s Template<\/h3>\n<p>The final step is to update the <code>home.html<\/code> template to display the todos we stored in our todos array.<\/p>\n<p>To do this let\u2019s add the following markup:<\/p>\n<pre><code class=\"html\">&lt;!-- home.html --&gt;\n  &lt;ion-navbar primary *navbar&gt;\n    &lt;ion-title&gt;\n      MEAN Ionic 2 Todo App\n    &lt;\/ion-title&gt;\n  &lt;\/ion-navbar&gt;\n  &lt;ion-content class=&quot;home&quot; padding&gt;\n    &lt;h2&gt;Add a Todo&lt;\/h2&gt;\n    &lt;ion-item no-lines&gt;\n      &lt;ion-input #newTodo (keyup.enter)=&quot;return;&quot; type=&quot;text&quot; placeholder=&quot;Add new todo...&quot; &gt;&lt;\/ion-input&gt;\n      &lt;button clear large item-right (click)=&quot;return;&quot;&gt;\n        &lt;ion-icon name=&quot;add&quot;&gt; &lt;\/ion-icon&gt;\n      &lt;\/button&gt;\n    &lt;\/ion-item&gt;\n    &lt;h2&gt;Todo List &lt;small&gt;Swipe a todo to edit or delete&lt;\/small&gt;&lt;\/h2&gt;\n    &lt;ion-list no-lines&gt;\n      &lt;ion-item-sliding #slidingItem *ngFor=&quot;let todo of todos&quot;&gt;\n        &lt;ion-item&gt;\n          &lt;ion-checkbox (click)=&quot;return;&quot; [checked]=&quot;todo.isComplete&quot;&gt;&lt;\/ion-checkbox&gt;\n          &lt;ion-item text-wrap item-left [class.completed]=&quot;todo.isComplete&quot;&gt;\n            {{ todo.description }}\n          &lt;\/ion-item&gt;\n        &lt;\/ion-item&gt;\n        &lt;ion-item-options (ionSwipe)=&quot;&quot;&gt;\n          &lt;button (click)=&quot;return;&quot;&gt;Edit&lt;\/button&gt;\n          &lt;button danger (click)=&quot;return;&quot;&gt;\n            &lt;ion-icon name=&quot;trash&quot;&gt;&lt;\/ion-icon&gt;\n          &lt;\/button&gt;\n        &lt;\/ion-item-options&gt;\n      &lt;\/ion-item-sliding&gt;\n    &lt;\/ion-list&gt;\n  &lt;\/ion-content&gt;\n<\/code><\/pre>\n<p>While we\u2019ve added quite a bit into this file, the most important piece to notice is the <a href=\"https:\/\/angular.io\/docs\/ts\/latest\/api\/common\/NgFor-directive.html\"><code>*ngFor<\/code><\/a> directive we have on the <a href=\"http:\/\/ionicframework.com\/docs\/v2\/api\/components\/item\/ItemSliding\/\"><code>ionic-item-sliding<\/code> component<\/a>.<\/p>\n<pre><code class=\"javascript\">  *ngFor=&quot;let todo of todos&quot;\n<\/code><\/pre>\n<p>Here we are defining a loop variable with <code>let todo<\/code> that will receive a <code>Todo<\/code> from our todos array defined in our Home Component class. Within this newly instantiated template for each <code>Todo<\/code>, we\u2019ll access and alter the properties of each todo.<\/p>\n<p>Right off the bat, you can see us using <code>todo.description<\/code> to render <code>{{ }}<\/code> our Todo\u2019s description, and <code>todo.isComplete<\/code> on several binding properties <code>[ ]<\/code> to either add a class or check a checkbox. Finally, you will also notice several spots where we\u2019re handling events such as <code>(click)<\/code> and <code>(keyup.enter)<\/code>, but instead of making actual function calls,\u00a0we will just <code>return;<\/code> for each event. We\u2019ll get those working in the next post.<\/p>\n<h3>Styles to Make Things Purdy<\/h3>\n<p>Although the utilitarian among us may be shaking their heads, let\u2019s go ahead and add styles for our app to the <code>app\/theme\/app.core.scss<\/code> file. Below the <code>import<\/code> statement, add the following:<\/p>\n<pre><code class=\"css\">  \/\/ app.core.scss\n  h2 {\n    color: color($colors, dark);\n    font-size: 1.7rem;\n    margin:10px 0 0;\n    small {\n      color: lighten(color($colors, dark), 20%);\n      font-weight: normal;\n    }\n  }\n\n  ion-list {\n    &gt;ion-item-sliding {\n      border-bottom: 1px solid color($colors, light);\n\n      .item,\n      &amp;:last-child .item {\n        border:none;\n        margin:0;\n      }\n\n      .completed {\n          text-decoration: line-through;\n          font-style: italic;\n      }\n    }\n  }\n\n  ion-textarea{\n    .text-input {\n      font-size: 1.6rem;\n      color: color($colors, dark);\n      margin:0;\n      padding:8px;\n      border:1px solid color($colors, light);\n      border-radius:3px;\n    }\n  }\n<\/code><\/pre>\n<p>You might notice some unused things in there &#8212; don\u2019t worry, we\u2019ll be adding more markup to our app in next post.<\/p>\n<h3>Serve it Up<\/h3>\n<p>If you\u2019d like to see what things look like thus far, head over to your terminal and open up two tabs, one to run the ionic build server and one to run our backend server.<\/p>\n<pre><code>  $\/todo-ionic2-heroku &gt; ionic serve\n  $\/todo-ionic2-heroku &gt; node server.js\n<\/code><\/pre>\n<p>Ionic will open up port 8100 for the build server, but if we want to see our Todos, open localhost:8080. Assuming you\u2019re also using a device viewer in your browser of choice, you should hopefully see something like this:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"241\" height=\"428\" data-src=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2016\/08\/todo-app.png\" alt=\"todo app\" class=\"alignnone size-full wp-image-1382 lazyload\" data-srcset=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2016\/08\/todo-app.png 241w, https:\/\/ionic.io\/blog\/wp-content\/uploads\/2016\/08\/todo-app-169x300.png 169w\" data-sizes=\"auto, (max-width: 241px) 100vw, 241px\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" style=\"--smush-placeholder-width: 241px; --smush-placeholder-aspect-ratio: 241\/428;\" \/><noscript><img loading=\"lazy\" decoding=\"async\" width=\"241\" height=\"428\" src=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2016\/08\/todo-app.png\" alt=\"todo app\" class=\"alignnone size-full wp-image-1382\" srcset=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2016\/08\/todo-app.png 241w, https:\/\/ionic.io\/blog\/wp-content\/uploads\/2016\/08\/todo-app-169x300.png 169w\" sizes=\"auto, (max-width: 241px) 100vw, 241px\" \/><\/noscript> <img loading=\"lazy\" decoding=\"async\" width=\"240\" height=\"428\" data-src=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2016\/08\/todo-app-slide.png\" alt=\"todo app slide\" class=\"alignnone size-full wp-image-1383 lazyload\" data-srcset=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2016\/08\/todo-app-slide.png 240w, https:\/\/ionic.io\/blog\/wp-content\/uploads\/2016\/08\/todo-app-slide-168x300.png 168w\" data-sizes=\"auto, (max-width: 240px) 100vw, 240px\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" style=\"--smush-placeholder-width: 240px; --smush-placeholder-aspect-ratio: 240\/428;\" \/><noscript><img loading=\"lazy\" decoding=\"async\" width=\"240\" height=\"428\" src=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2016\/08\/todo-app-slide.png\" alt=\"todo app slide\" class=\"alignnone size-full wp-image-1383\" srcset=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2016\/08\/todo-app-slide.png 240w, https:\/\/ionic.io\/blog\/wp-content\/uploads\/2016\/08\/todo-app-slide-168x300.png 168w\" sizes=\"auto, (max-width: 240px) 100vw, 240px\" \/><\/noscript><\/p>\n<p>So awesome, right!? I just called my Grandma to tell her we just displayed real data using Ionic 2\/Angular 2. She\u2019s so proud!<\/p>\n<h3>Concluding Thoughts<\/h3>\n<p>Literally nothing can stop you now. You\u2019re becoming a Pok\u00e9mon Master\u2026 I mean an Ionic 2 Wizard! In this post we wrote an HTTP service to collect todos from our MongoDB database, set up our view logic to utilize that service, and designed the front end of our simple app. We also learned a bit about Observables and did some type-checking with TypeScript.<\/p>\n<p>In the <a href=\"https:\/\/ionic.io\/blog\/one-mean-ionic-2-todo-app-on-heroku-part-3\/\">next and final post<\/a>, we\u2019ll flesh out the details to allow us to fully interact with our Ionic 2 app. Specifically, we\u2019ll flesh out the <code>TodoService<\/code> to <code>POST<\/code> (add), <code>PUT<\/code> (update) and <code>DELETE<\/code> (..um, well, delete) Todos. Then we\u2019ll link this up to the app\u2019s view. We\u2019ll also add another page to our app to isolate and edit todos.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In part 1 of this series, we started building an end-to-end Ionic 2 app with a Node.js backend. If you\u2019re just joining us now, you\u2019ll probably want to stop and go back to the first post. Up to this point, we\u2019ve worked primarily in the server.js file where we created an Express app and defined [&hellip;]<\/p>\n","protected":false},"author":30,"featured_media":1322,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"publish_to_discourse":"","publish_post_category":"","wpdc_auto_publish_overridden":"","wpdc_topic_tags":"","wpdc_pin_topic":"","wpdc_pin_until":"","discourse_post_id":"","discourse_permalink":"","wpdc_publishing_response":"","wpdc_publishing_error":"","_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1],"tags":[23,13,25],"class_list":["post-1315","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-all","tag-framework","tag-ionic-2","tag-tutorials"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v23.0 (Yoast SEO v23.0) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>One MEAN Ionic 2 Todo App on Heroku, Part 2 - Ionic Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/ionic.io\/blog\/one-mean-ionic-2-todo-app-on-heroku-part-2\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"One MEAN Ionic 2 Todo App on Heroku, Part 2\" \/>\n<meta property=\"og:description\" content=\"In part 1 of this series, we started building an end-to-end Ionic 2 app with a Node.js backend. If you\u2019re just joining us now, you\u2019ll probably want to stop and go back to the first post. Up to this point, we\u2019ve worked primarily in the server.js file where we created an Express app and defined [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/ionic.io\/blog\/one-mean-ionic-2-todo-app-on-heroku-part-2\" \/>\n<meta property=\"og:site_name\" content=\"Ionic Blog\" \/>\n<meta property=\"article:published_time\" content=\"2016-08-18T15:32:02+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2016-09-01T05:44:12+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2016\/08\/Ionic-2-Heroku-Left.png\" \/>\n\t<meta property=\"og:image:width\" content=\"241\" \/>\n\t<meta property=\"og:image:height\" content=\"428\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Justin Leatherwood\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@ionicframework\" \/>\n<meta name=\"twitter:site\" content=\"@ionicframework\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Justin Leatherwood\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/ionic.io\/blog\/one-mean-ionic-2-todo-app-on-heroku-part-2#article\",\"isPartOf\":{\"@id\":\"https:\/\/ionic.io\/blog\/one-mean-ionic-2-todo-app-on-heroku-part-2\"},\"author\":{\"name\":\"Justin Leatherwood\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/person\/ebd8f9961dbecd11be74bf51d440689b\"},\"headline\":\"One MEAN Ionic 2 Todo App on Heroku, Part 2\",\"datePublished\":\"2016-08-18T15:32:02+00:00\",\"dateModified\":\"2016-09-01T05:44:12+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/ionic.io\/blog\/one-mean-ionic-2-todo-app-on-heroku-part-2\"},\"wordCount\":1046,\"commentCount\":10,\"publisher\":{\"@id\":\"https:\/\/ionic.io\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/ionic.io\/blog\/one-mean-ionic-2-todo-app-on-heroku-part-2#primaryimage\"},\"thumbnailUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2016\/08\/Ionic-2-Heroku-Left.png\",\"keywords\":[\"Framework\",\"Ionic 2\",\"Tutorials\"],\"articleSection\":[\"All\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/ionic.io\/blog\/one-mean-ionic-2-todo-app-on-heroku-part-2#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/ionic.io\/blog\/one-mean-ionic-2-todo-app-on-heroku-part-2\",\"url\":\"https:\/\/ionic.io\/blog\/one-mean-ionic-2-todo-app-on-heroku-part-2\",\"name\":\"One MEAN Ionic 2 Todo App on Heroku, Part 2 - Ionic Blog\",\"isPartOf\":{\"@id\":\"https:\/\/ionic.io\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/ionic.io\/blog\/one-mean-ionic-2-todo-app-on-heroku-part-2#primaryimage\"},\"image\":{\"@id\":\"https:\/\/ionic.io\/blog\/one-mean-ionic-2-todo-app-on-heroku-part-2#primaryimage\"},\"thumbnailUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2016\/08\/Ionic-2-Heroku-Left.png\",\"datePublished\":\"2016-08-18T15:32:02+00:00\",\"dateModified\":\"2016-09-01T05:44:12+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/ionic.io\/blog\/one-mean-ionic-2-todo-app-on-heroku-part-2#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/ionic.io\/blog\/one-mean-ionic-2-todo-app-on-heroku-part-2\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/ionic.io\/blog\/one-mean-ionic-2-todo-app-on-heroku-part-2#primaryimage\",\"url\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2016\/08\/Ionic-2-Heroku-Left.png\",\"contentUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2016\/08\/Ionic-2-Heroku-Left.png\",\"width\":241,\"height\":428},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/ionic.io\/blog\/one-mean-ionic-2-todo-app-on-heroku-part-2#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/ionic.io\/blog\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"One MEAN Ionic 2 Todo App on Heroku, Part 2\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/ionic.io\/blog\/#website\",\"url\":\"https:\/\/ionic.io\/blog\/\",\"name\":\"ionic.io\/blog\",\"description\":\"Build amazing native and progressive web apps with the web\",\"publisher\":{\"@id\":\"https:\/\/ionic.io\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/ionic.io\/blog\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/ionic.io\/blog\/#organization\",\"name\":\"Ionic\",\"url\":\"https:\/\/ionic.io\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png\",\"contentUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png\",\"width\":1920,\"height\":854,\"caption\":\"Ionic\"},\"image\":{\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/x.com\/ionicframework\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/person\/ebd8f9961dbecd11be74bf51d440689b\",\"name\":\"Justin Leatherwood\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/b618dcf46835261d07da1f0caf5847b8cf86ac4aae30f6073764ed6747e57544?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/b618dcf46835261d07da1f0caf5847b8cf86ac4aae30f6073764ed6747e57544?s=96&d=mm&r=g\",\"caption\":\"Justin Leatherwood\"},\"url\":\"https:\/\/ionic.io\/blog\/author\/justin\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"One MEAN Ionic 2 Todo App on Heroku, Part 2 - Ionic Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/ionic.io\/blog\/one-mean-ionic-2-todo-app-on-heroku-part-2","og_locale":"en_US","og_type":"article","og_title":"One MEAN Ionic 2 Todo App on Heroku, Part 2","og_description":"In part 1 of this series, we started building an end-to-end Ionic 2 app with a Node.js backend. If you\u2019re just joining us now, you\u2019ll probably want to stop and go back to the first post. Up to this point, we\u2019ve worked primarily in the server.js file where we created an Express app and defined [&hellip;]","og_url":"https:\/\/ionic.io\/blog\/one-mean-ionic-2-todo-app-on-heroku-part-2","og_site_name":"Ionic Blog","article_published_time":"2016-08-18T15:32:02+00:00","article_modified_time":"2016-09-01T05:44:12+00:00","og_image":[{"width":241,"height":428,"url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2016\/08\/Ionic-2-Heroku-Left.png","type":"image\/png"}],"author":"Justin Leatherwood","twitter_card":"summary_large_image","twitter_creator":"@ionicframework","twitter_site":"@ionicframework","twitter_misc":{"Written by":"Justin Leatherwood","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/ionic.io\/blog\/one-mean-ionic-2-todo-app-on-heroku-part-2#article","isPartOf":{"@id":"https:\/\/ionic.io\/blog\/one-mean-ionic-2-todo-app-on-heroku-part-2"},"author":{"name":"Justin Leatherwood","@id":"https:\/\/ionic.io\/blog\/#\/schema\/person\/ebd8f9961dbecd11be74bf51d440689b"},"headline":"One MEAN Ionic 2 Todo App on Heroku, Part 2","datePublished":"2016-08-18T15:32:02+00:00","dateModified":"2016-09-01T05:44:12+00:00","mainEntityOfPage":{"@id":"https:\/\/ionic.io\/blog\/one-mean-ionic-2-todo-app-on-heroku-part-2"},"wordCount":1046,"commentCount":10,"publisher":{"@id":"https:\/\/ionic.io\/blog\/#organization"},"image":{"@id":"https:\/\/ionic.io\/blog\/one-mean-ionic-2-todo-app-on-heroku-part-2#primaryimage"},"thumbnailUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2016\/08\/Ionic-2-Heroku-Left.png","keywords":["Framework","Ionic 2","Tutorials"],"articleSection":["All"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/ionic.io\/blog\/one-mean-ionic-2-todo-app-on-heroku-part-2#respond"]}]},{"@type":"WebPage","@id":"https:\/\/ionic.io\/blog\/one-mean-ionic-2-todo-app-on-heroku-part-2","url":"https:\/\/ionic.io\/blog\/one-mean-ionic-2-todo-app-on-heroku-part-2","name":"One MEAN Ionic 2 Todo App on Heroku, Part 2 - Ionic Blog","isPartOf":{"@id":"https:\/\/ionic.io\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/ionic.io\/blog\/one-mean-ionic-2-todo-app-on-heroku-part-2#primaryimage"},"image":{"@id":"https:\/\/ionic.io\/blog\/one-mean-ionic-2-todo-app-on-heroku-part-2#primaryimage"},"thumbnailUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2016\/08\/Ionic-2-Heroku-Left.png","datePublished":"2016-08-18T15:32:02+00:00","dateModified":"2016-09-01T05:44:12+00:00","breadcrumb":{"@id":"https:\/\/ionic.io\/blog\/one-mean-ionic-2-todo-app-on-heroku-part-2#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/ionic.io\/blog\/one-mean-ionic-2-todo-app-on-heroku-part-2"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/ionic.io\/blog\/one-mean-ionic-2-todo-app-on-heroku-part-2#primaryimage","url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2016\/08\/Ionic-2-Heroku-Left.png","contentUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2016\/08\/Ionic-2-Heroku-Left.png","width":241,"height":428},{"@type":"BreadcrumbList","@id":"https:\/\/ionic.io\/blog\/one-mean-ionic-2-todo-app-on-heroku-part-2#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/ionic.io\/blog"},{"@type":"ListItem","position":2,"name":"One MEAN Ionic 2 Todo App on Heroku, Part 2"}]},{"@type":"WebSite","@id":"https:\/\/ionic.io\/blog\/#website","url":"https:\/\/ionic.io\/blog\/","name":"ionic.io\/blog","description":"Build amazing native and progressive web apps with the web","publisher":{"@id":"https:\/\/ionic.io\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/ionic.io\/blog\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/ionic.io\/blog\/#organization","name":"Ionic","url":"https:\/\/ionic.io\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png","contentUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png","width":1920,"height":854,"caption":"Ionic"},"image":{"@id":"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/ionicframework"]},{"@type":"Person","@id":"https:\/\/ionic.io\/blog\/#\/schema\/person\/ebd8f9961dbecd11be74bf51d440689b","name":"Justin Leatherwood","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/ionic.io\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/b618dcf46835261d07da1f0caf5847b8cf86ac4aae30f6073764ed6747e57544?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/b618dcf46835261d07da1f0caf5847b8cf86ac4aae30f6073764ed6747e57544?s=96&d=mm&r=g","caption":"Justin Leatherwood"},"url":"https:\/\/ionic.io\/blog\/author\/justin"}]}},"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2016\/08\/Ionic-2-Heroku-Left.png","_links":{"self":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/posts\/1315","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/users\/30"}],"replies":[{"embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/comments?post=1315"}],"version-history":[{"count":0,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/posts\/1315\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/media\/1322"}],"wp:attachment":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/media?parent=1315"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/categories?post=1315"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/tags?post=1315"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}