{"id":22442,"date":"2018-08-23T12:15:00","date_gmt":"2018-08-23T09:15:00","guid":{"rendered":"https:\/\/www.webcodegeeks.com\/?p=22442"},"modified":"2018-08-22T15:31:19","modified_gmt":"2018-08-22T12:31:19","slug":"sms-groceries-app-ionic-angular","status":"publish","type":"post","link":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/sms-groceries-app-ionic-angular\/","title":{"rendered":"Build an SMS Groceries App with Ionic and Angular"},"content":{"rendered":"<p>In this article, we\u2019re going to have a closer look at the Ionic Framework, which is a modern WEB-based platform for building mobile apps. That means you don\u2019t need to have any knowledge about the mobile platforms to build real apps.<\/p>\n<p>Ionic is a full platform which evolved from a simple UI library. It\u2019s a complete gateway for a web developer into the mobile world. It is still a UI framework and a very good one. It\u2019s also a set of abstractions on top of the Cordova, which provides JavaScript bindings for the native functions. In the heart of it is a well-known web framework Angular with TypeScript.<\/p>\n<p>Ionic will run your code in a webview (a simple browser) with the help of some native bindings. Note how this is different from <a href=\"https:\/\/facebook.github.io\/react-native\/\">React Native<\/a>, which will actually transpile the web code into the native components.<\/p>\n<p>As we\u2019re getting familiar with Ionic, we\u2019re going to make something very practical. We\u2019re going to build a mobile app \u2014 one that solves a real problem. The idea behind it comes from the very real problem I\u2019ve been suffering from for several years. Namely the groceries list. My wife sends me a list of things I need to buy in an SMS, which is usually quite long. And so you can imagine, it\u2019s hard to keep track of what is already in the shopping basket and what\u2019s not.<\/p>\n<p>So let\u2019s build an app that will read the SMS and make a nice To Do list with checkboxes from it.<\/p>\n<p><a href=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/08\/Grocery-Store-App_8.21.18.png\"><img decoding=\"async\" class=\"aligncenter wp-image-22446 size-full\" src=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/08\/Grocery-Store-App_8.21.18.png\" alt=\"ionic\" width=\"300\" height=\"411\" srcset=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/08\/Grocery-Store-App_8.21.18.png 300w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2018\/08\/Grocery-Store-App_8.21.18-219x300.png 219w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>The complete code can be found <a href=\"https:\/\/github.com\/hiquest\/article-sms-groceries-list\">on GitHub<\/a>. In case there are problems, please refer to the source code.<\/p>\n<h2>Prerequisites<\/h2>\n<p>You probably already have the Node and the <a href=\"https:\/\/docs.npmjs.com\/\">npm package manager<\/a>. You\u2019ll also want to <a href=\"https:\/\/developer.android.com\/studio\/\">install Android Studio<\/a> which comes with an Android SDK. We will need it to build our app for Android and run it on the emulator or a real device.<\/p>\n<h2>Getting Started<\/h2>\n<p>Alright, first off, open the terminal and install the ionic client.<\/p>\n<pre class=\"brush:bash\">npm i -g ionic<\/pre>\n<p>You can also add a handy alias into your shell config file.<\/p>\n<pre class=\"brush:bash\">alias i=ionic<\/pre>\n<p>When creating a new project, you can specify a template to build from. For the sake of this tutorial, we\u2019ll start with the blank.<\/p>\n<pre class=\"brush:bash\">ionic start sms-shop blank\r\ncd sms-shop<\/pre>\n<p>Ionic will create a new project, install all the dependencies, and then you\u2019ll be able to run it.<\/p>\n<pre class=\"brush:bash\">ionic serve<\/pre>\n<p>You should see your blank app in the browser now. That is how you\u2019re supposed to develop your app. Every time you make a change, the browser will refresh, and you will see the change on the screen. It\u2019s pretty handy to have a separate monitor with the browser always in sight.<\/p>\n<p>Sometimes, you will want to run your app on a real device or an emulator (because Cordova plugins won\u2019t work in a browser).<\/p>\n<pre class=\"brush:bash\">ionic cordova run android --device\r\nionic cordova run android --emulator<\/pre>\n<p>The downside is that every time you alter an app, you have to re-run it to see the changes. Unfortunately, this is the only way we can test the native functions.<\/p>\n<h2>Here\u2019s the plan\u2026<\/h2>\n<p>OK, let\u2019s talk about what we are going to do.<\/p>\n<p>We will need three pages. The first one to display all the lists we have (we already have the HomePage), the second one to select an SMS to build a list from <code>(SelectPage)<\/code>, and the last one is the page for a specific groceries list where you can check\/uncheck items <code>(ListPage)<\/code>.<\/p>\n<p>What would a groceries list look like? It will have an id, date of creation and the list of items. Each item will have a title and a boolean flag \u201cdone.\u201d As you already know, Ionic is built on top of the Angular with the TypeScript support. So let\u2019s define our groceries list type. Create a new file <code>src\/app\/types.ts<\/code>:<\/p>\n<pre class=\"brush:java\">export type GLIST = {\r\n  id: string,\r\n  created: string,\r\n  items: Array&lt; { title: string, done: boolean }&gt;\r\n}<\/pre>\n<p>Our app will also need some storage to store the lists and the items. For that, we\u2019ll use the <a href=\"https:\/\/ionicframework.com\/docs\/storage\/\">Ionic Storage module<\/a>. Ionic Storage lets us store data as key-values, and underneath it, will use a storage engine, which is the most suitable for a specific platform.<\/p>\n<p>To make the storage available, we\u2019ll need to register it as an import. In the <code>src\/app\/app.module.ts<\/code> file, let\u2019s import storage, and put it into the imports section:<\/p>\n<pre class=\"brush:java\">import { IonicStorageModule } from '@ionic\/storage';\r\n\/\/ ...\r\n imports: [\r\n    BrowserModule,\r\n    IonicModule.forRoot(MyApp),\r\n    IonicStorageModule.forRoot()\r\n  ],\r\n\/\/ ...<\/pre>\n<p>OK, now we\u2019re all set to actually start making things.<\/p>\n<h2>Home view<\/h2>\n<p>Let\u2019s start with the home view. Here we\u2019re going to display all the groceries lists and a button that will allow us to create a new list from an SMS. Open <code>home.html<\/code> and replace its content with the following:<\/p>\n<pre class=\"brush:html\">&lt;ion -header&gt;\r\n  &lt;\/ion&gt;&lt;ion -navbar&gt;\r\n    &lt;\/ion&gt;&lt;ion -title&gt;SMS Groceries&lt;\/ion&gt;\r\n  \r\n&lt;ion -content padding&gt;\r\n  &lt;p text-center&gt;\r\n    &lt;button ion-button (click)=\"selectSms()\"&gt;Select SMS&lt;\/button&gt;\r\n  &lt;\/p&gt;\r\n\r\n  &lt;\/ion&gt;&lt;ion -list&gt;\r\n    &lt;\/ion&gt;&lt;ion -item *ngFor=\"let list of lists\" (click)=\"go(list.id)\"&gt;\r\n      \r\n      {{ listTitle(list) }}\r\n      &lt;span item-end style='color: #aaa;'&gt;{{ list.created }}&lt;\/span&gt;<\/pre>\n<p>In this view, <code>ion-header<\/code> and <code>ion-list<\/code> are examples of ionic UI components. For a full list of available components, you can refer to <a href=\"https:\/\/ionicframework.com\/docs\/components\/\">the documentation<\/a>.<\/p>\n<p>The most interesting part here is:<\/p>\n<pre class=\"brush:html\">&lt;ion -item *ngFor=\"let list of lists\" (click)=\"go(list.id)\"&gt;\r\n    {{ listTitle(list) }}\r\n    &lt;span item-end style='color: #aaa;'&gt;{{ list.created }}&lt;\/span&gt;\r\n  &lt;\/ion&gt;<\/pre>\n<p>If you\u2019re not familiar with Angular, here\u2019s a quick overview:<\/p>\n<ul>\n<li><code>ngFor=\"let list of lists\"<\/code> \u2013 is a common directive for iterating a list in Angular.<\/li>\n<li><code>(click)=\"go(list.id)\"<\/code> \u2013 this is how you bind a click event. In this case we want to navigate to the list view<\/li>\n<li><code>{{ listTitle(list) }}<\/code> \u2013 every time you want to output a value you put it into double curvy braces<\/li>\n<li><code>ion-item, item-end<\/code> \u2013 those are UI components that Ionic prepared for us to use.<\/li>\n<\/ul>\n<p>OK, I hope this part is clear, now let\u2019s do the component. Copy and paste this into <code>home.ts<\/code>:<\/p>\n<pre class=\"brush:java\">import { Component } from \"@angular\/core\"\r\nimport { NavController } from \"ionic-angular\"\r\nimport { Storage } from \"@ionic\/storage\"\r\n\r\nimport { SelectPage } from \"..\/select\/select\"\r\nimport { ListPage } from \"..\/list\/list\"\r\nimport { GLIST } from \"..\/..\/app\/types\"\r\n\r\n@Component({\r\n  selector: \"page-home\",\r\n  templateUrl: \"home.html\"\r\n})\r\nexport class HomePage {\r\n  lists: Array&lt;glist&gt;  \/\/ define our lists, which is an array of GLISTs\r\n\r\n  constructor(\r\n    public navCtrl: NavController,  \/\/ navCtrl is used for navigation between pages\r\n    private storage: Storage        \/\/ storage to be used for... well storing our data\r\n  ) {}\r\n\r\n  \/\/ this is part of Ionic lifecycle; it will be called every time before navigating this page\r\n  ionViewWillEnter() {\r\n    \/\/ we're loading all the lists that we have from the storage\r\n    const lists = []\r\n    this.storage.forEach((list, id) =&gt; {\r\n      lists.push(JSON.parse(list))\r\n      console.log(this.lists)\r\n    }).then(() =&gt; {\r\n      this.lists = lists\r\n    })\r\n  }\r\n\r\n  selectSms() {\r\n    this.navCtrl.push(SelectPage, {})  \/\/ this is how we change the page\r\n  }\r\n\r\n  listTitle(list) {\r\n    return list.items.map(x =&gt; x.title).join(\", \")\r\n  }\r\n\r\n  go(id) {\r\n    this.navCtrl.push(ListPage, {id})  \/\/ another example of changing the page,\r\n                                       \/\/ this time with a parameter\r\n  }\r\n}&lt;\/glist&gt;<\/pre>\n<p>Now, this might feel a little overwhelming, so let\u2019s break this code down piece by piece.<\/p>\n<p>First of all, in Angular when you want to use a component, you are using dependency injection. Basically, you\u2019re not creating the components yourself, but rather declaring which ones you need and letting the engine figure out the details. In the example above, this is how we inject navCtrl and storage. Angular will create them for us and put on <code>this<\/code>.<\/p>\n<p>The <code>ionViewWillEnter<\/code> is part of the <a href=\"https:\/\/ionicframework.com\/docs\/api\/navigation\/NavController\/\">Ionic page lifecycle<\/a>. This method runs just before the page is to become active. This is usually the place where you want to load your data. This is what we are doing here by loading all of our lists from the <code>storage<\/code>.<\/p>\n<p>You\u2019ve probably noticed that storage works asynchronously. Instead of returning a value, it returns a promise. The same goes for the <code>forEach<\/code> method we\u2019re using here.<\/p>\n<p>Finally, when we want to navigate to another page, we use the <code>navCtrl<\/code> which works like a simple stack. It has a push method we need to call whenever we want the view to change. It can also accept the params, which can be retrieved on the next page (we\u2019ll talk about this later).<\/p>\n<p>At this point, the compiler will fail because we still haven\u2019t defined the other two pages <code>SelectPage<\/code> and <code>ListPage<\/code>. So let\u2019s write them.<\/p>\n<h2>Reading the SMSes<\/h2>\n<p>A couple of words about Ionic Native. Loosely speaking, this is a set of JavaScript bindings for some native behavior. It allows you to use some of the native phone functions (for example camera) from JavaScript. Underneath it is <a href=\"https:\/\/cordova.apache.org\/docs\/en\/latest\/\">powered by Cordova<\/a>, but I think nowadays you can even <a href=\"https:\/\/docs.microsoft.com\/en-us\/xamarin\/\">swap it to Xamarin<\/a> which is owned by Microsoft.<\/p>\n<p>The list of Native\u2019s features is astonishingly long. You can skim through the <a href=\"https:\/\/ionicframework.com\/docs\/native\/\">whole list here<\/a>.<\/p>\n<p>Some of those plugins can be used on both platforms iOS, and Android, while others are platform-specific.<\/p>\n<p>Our task here is to read the list of SMSes and let the users select the SMS they want. I have to say that iOS doesn\u2019t have an ability to read SMSes (at least not that I\u2019m aware of, please let me know otherwise). So from this point onwards, we\u2019re going Android-only.<\/p>\n<p>Let\u2019s start by using a permissions module. It allows us to ask for a particular permission at any point of the code (this is how the modern Android permission system works).<\/p>\n<pre class=\"brush:bash\">ionic cordova plugin add cordova-plugin-android-permissions\r\nnpm install --save @ionic-native\/android-permissions<\/pre>\n<p>Then, in the <code>app.module.ts<\/code> add to the providers section:<\/p>\n<pre class=\"brush:java\">import { AndroidPermissions} from '@ionic-native\/android-permissions';\r\n\/\/ ...\r\n  providers: [\r\n    StatusBar,\r\n    SplashScreen,\r\n    {provide: ErrorHandler, useClass: IonicErrorHandler},\r\n    AndroidPermissions  \/\/ &lt; = this change\r\n  ]<\/pre>\n<p>We will also need the Cordova plugin for reading the SMSes:<\/p>\n<pre class=\"brush:bash\">ionic cordova plugin add cordova-plugin-sms<\/pre>\n<p>Now let\u2019s create the <code>SelectPage<\/code>. This time let\u2019s start with the component itself:<\/p>\n<pre class=\"brush:java\">\/\/ app\/pages\/select\/select.ts\r\n\r\nimport { Component } from \"@angular\/core\"\r\nimport { NavController, Platform } from \"ionic-angular\"\r\nimport { AndroidPermissions } from \"@ionic-native\/android-permissions\"\r\nimport { ListPage } from \"..\/list\/list\"\r\nimport { Storage } from \"@ionic\/storage\"\r\n\r\nimport { GLIST } from \"..\/..\/app\/types\"\r\n\r\ndeclare var SMS: any  \/\/ making TypeScript happy. Otherwise, we could use `window.SMS`\r\n\r\n@Component({\r\n  selector: \"page-select\",\r\n  templateUrl: \"select.html\"\r\n})\r\nexport class SelectPage {\r\n  messages: Array&lt;any&gt;  \/\/ Our messages definition\r\n\r\n  constructor(\r\n    public navCtrl: NavController,\r\n    public androidPermissions: AndroidPermissions,  \/\/ a component for requesting permissions\r\n    public platform: Platform,\r\n    private storage: Storage,\r\n  ) {\r\n    this.messages = []\r\n  }\r\n\r\n  select(m) {\r\n    const id = m.date + \"\"\r\n    const list: GLIST = {\r\n      id,\r\n      created: formatDate(new Date()),\r\n      items: m.body.split(\",\").map(s =&gt; {\r\n        return {\r\n          title: s.trim(),\r\n          done: false,\r\n        }\r\n      })\r\n    }\r\n    this.storage.set(id, JSON.stringify(list))\r\n    this.navCtrl.push(ListPage, { id })\r\n  }\r\n\r\n  loadMessages() {\r\n    this.platform.ready().then(readySource =&gt; {\r\n      SMS.listSMS(\r\n        { box: \"inbox\", indexFrom: 0, maxCount: 50 },\r\n        messages =&gt; {\r\n          console.log(\"Sms\", messages)\r\n          this.messages = messages\r\n        },\r\n        err =&gt; console.log(\"error listing smses: \" + err)\r\n      )\r\n    })\r\n  }\r\n\r\n  ionViewWillEnter() {\r\n    const READ_SMS = this.androidPermissions.PERMISSION.READ_SMS\r\n    this.androidPermissions.checkPermission(READ_SMS).then(\r\n      success =&gt; {\r\n        console.log(\"Permission granted\")\r\n        this.loadMessages()\r\n      },\r\n      err =&gt; this.androidPermissions.requestPermission(READ_SMS)\r\n    )\r\n\r\n    this.androidPermissions.requestPermissions([READ_SMS])\r\n  }\r\n}\r\n\r\n\/\/ A simple formatter for dates, i.e. \"4 Feb\"\r\nfunction formatDate(date) {\r\n  var monthNames = [\r\n    \"Jan\", \"Feb\", \"Mar\", \"Apr\",\r\n    \"May\", \"Jun\", \"Jul\", \"Aug\",\r\n    \"Sep\", \"Oct\", \"Nov\", \"Dec\"\r\n  ]\r\n\r\n  var day = date.getDate();\r\n  var monthIndex = date.getMonth();\r\n\r\n  return day + ' ' + monthNames[monthIndex];\r\n}&lt;\/any&gt;<\/pre>\n<p>Let\u2019s start with the method:<\/p>\n<pre class=\"brush:java\">ionViewWillEnter() {\r\n    const READ_SMS = this.androidPermissions.PERMISSION.READ_SMS\r\n    this.androidPermissions.checkPermission(READ_SMS).then(\r\n      success =&gt; {\r\n        console.log(\"Permission granted\")\r\n        this.loadMessages()\r\n      },\r\n      err =&gt; this.androidPermissions.requestPermission(READ_SMS)\r\n    )\r\n    this.androidPermissions.requestPermissions([READ_SMS])\r\n  }<\/pre>\n<p>You already know this method runs every time a view is about to enter. Here, we\u2019re using the permission component that will trigger a standard Android permission dialog asking if we can read the SMSes. And if we have the permission, then it will load the messages:<\/p>\n<pre class=\"brush:java\">loadMessages() {\r\n    this.platform.ready().then(readySource =&gt; {\r\n      SMS.listSMS(\r\n        { box: \"inbox\", indexFrom: 0, maxCount: 50 },\r\n        messages =&gt; {\r\n          console.log(\"Sms\", messages)\r\n          this.messages = messages\r\n        },\r\n        err =&gt; console.log(\"error listing smses: \" + err)\r\n      )\r\n    })\r\n  }<\/pre>\n<p>Here, we\u2019re using the SMS module and one of its methods called <code>listSMS<\/code>. By the way, here you can <a href=\"https:\/\/github.com\/floatinghotpot\/cordova-plugin-sms\">read about others<\/a>. So, we read the first 50 SMSes and put them on <code>this<\/code> so that we can iterate them in the view.<\/p>\n<p>Then we also have the <code>select<\/code> method:<\/p>\n<pre class=\"brush:java\">select(m) {\r\n    const id = m.date + \"\"\r\n    const list: GLIST = {\r\n      id,\r\n      created: formatDate(new Date()),\r\n      items: m.body.split(\",\").map(s =&gt; {\r\n        return {\r\n          title: s.trim(),\r\n          done: false,\r\n        }\r\n      })\r\n    }\r\n    this.storage.set(id, JSON.stringify(list))\r\n    this.navCtrl.push(ListPage, { id })\r\n  }<\/pre>\n<p>It takes the SMS body, then it prepares the items list by splitting it with commas, puts it into the storage <code>this.storage.set(id, JSON.stringify(list))<\/code> and navigates to the list page, which we still need to write.<\/p>\n<p>And, finally the html view <code>(src\/pages\/select\/select.html)<\/code> should already be understandable:<\/p>\n<pre class=\"brush:html\">&lt;ion -header&gt;\r\n  &lt;\/ion&gt;&lt;ion -navbar&gt;\r\n    &lt;\/ion&gt;&lt;ion -title&gt;SMS Groceries&lt;\/ion&gt;\r\n\r\n\r\n&lt;ion -content padding&gt;\r\n\r\n  &lt;h1&gt;Select the SMS&lt;\/h1&gt;\r\n\r\n  &lt;\/ion&gt;&lt;ion -list&gt;\r\n    &lt;button ion-item *ngFor=\"let m of messages\" (click)=\"select(m)\"&gt;\r\n      {{ m.body }}\r\n    &lt;\/button&gt;\r\n  &lt;\/ion&gt;<\/pre>\n<h2>List Page<\/h2>\n<p>Just one little step left. Let\u2019s finally write the <code>ListPage<\/code>.<\/p>\n<pre class=\"brush:java\">import { Component } from \"@angular\/core\"\r\nimport { NavController, NavParams } from \"ionic-angular\"\r\nimport { Storage } from \"@ionic\/storage\"\r\n\r\nimport { GLIST } from \"..\/..\/app\/types\"\r\n\r\n@Component({\r\n  selector: \"page-list\",\r\n  templateUrl: \"list.html\"\r\n})\r\nexport class ListPage {\r\n  list: GLIST\r\n\r\n  constructor(\r\n    public navCtrl: NavController,\r\n    public navParams: NavParams,\r\n    private storage: Storage,\r\n  ) {\r\n  }\r\n\r\n  ionViewWillEnter() {\r\n    const id = this.navParams.get(\"id\")  \/\/ retrieving the param, in this case, list id\r\n    this.storage.get(id).then(list =&gt; {  \/\/ loading the list from the storage\r\n      if (list) {\r\n        this.list = JSON.parse(list)\r\n      } else {\r\n        console.log(\"NO LIST?!?!\")\r\n      }\r\n    })\r\n  }\r\n  \r\n  doneCount() {\r\n    return this.doneItems().length\r\n  }\r\n\r\n  allCount() {\r\n    if (!this.list) return 0\r\n    return this.list.items.length\r\n  }\r\n\r\n  toggle(item) {\r\n    item.done = !item.done\r\n    this.storage.set(this.list.id, JSON.stringify(this.list))\r\n  }\r\n\r\n  toBeDoneItems() {\r\n    if (!this.list) return []\r\n    return this.list.items.filter(x =&gt; !x.done)\r\n  }\r\n\r\n  doneItems() {\r\n    if (!this.list) return []\r\n    return this.list.items.filter(x =&gt; x.done)\r\n  }\r\n}<\/pre>\n<p>By this point, all of this should be familiar. Let\u2019s have a look at the HTML view:<\/p>\n<pre class=\"brush:html\">&lt;ion -header&gt;\r\n  &lt;\/ion&gt;&lt;ion -navbar&gt;\r\n    &lt;\/ion&gt;&lt;ion -title&gt;SMS Groceries&lt;\/ion&gt;\r\n  \r\n\r\n\r\n&lt;ion -content&gt;\r\n  &lt;\/ion&gt;&lt;ion -list&gt;\r\n\r\n    &lt;\/ion&gt;&lt;ion -item *ngFor=\"let item of toBeDoneItems()\" (click)=\"toggle(item)\"&gt;\r\n      &lt;span *ngIf=\"!item.done\"&gt;{{ item.title }}&lt;\/span&gt;\r\n      &lt;\/ion&gt;&lt;ion -icon name=\"square-outline\" item-end *ngIf=\"!item.done\"&gt;&lt;\/ion&gt;\r\n    \r\n\r\n    &lt;ion -item *ngFor=\"let item of doneItems()\" (click)=\"toggle(item)\"&gt;\r\n      &lt;span *ngIf=\"item.done\" style=\"text-decoration: line-through; color: #aaa;\"&gt;{{ item.title }}&lt;\/span&gt;\r\n      &lt;\/ion&gt;&lt;ion -icon name=\"checkbox-outline\" item-end *ngIf=\"item.done\" style='color: #aaa;'&gt;&lt;\/ion&gt;\r\n    \r\n\r\n  \r\n\r\n\r\n&lt;ion -footer&gt;\r\n  &lt;\/ion&gt;&lt;ion -toolbar&gt;\r\n    &lt;h2 padding&gt;Done: &lt;b&gt;{{ doneCount() }}&lt;\/b&gt; out of {{ allCount() }}&lt;\/h2&gt;\r\n  &lt;\/ion&gt;<\/pre>\n<h2>Running<\/h2>\n<p>Let\u2019s finally try to run our app with simple command (connect your Android device first):<\/p>\n<pre class=\"brush:bash\">i cordova run android --device<\/pre>\n<h2>Conclusion<\/h2>\n<p>Look, Ma!<\/p>\n<p>In this article we became familiar with Ionic Framework, got a grasp of Angular and Typescript, with dependency injection and rather peculiar HTML markup, and learned how to use native functions from our web app with the help of Cordova and Ionic Native.<\/p>\n<p>But what\u2019s more important\u2026<\/p>\n<p>In a matter of hours, with zero knowledge about mobile development, we were able to build a functioning application that uses native features and actually solves a real problem.<\/p>\n<p>It\u2019s the beauty and power of the Ionic Framework.<\/p>\n<p>I strongly encourage you to give it a try and build something useful (a side-project?), put it in the store and even try to get some money.<\/p>\n<p>Good luck and have fun.<\/p>\n<p>P.S.: Please let me know about any questions you have or if you need advice. I\u2019ll be happy to help. My twitter is <a href=\"https:\/\/twitter.com\/janis_t\/\">@janis_t<\/a>.<\/p>\n<div class=\"attribution\">\n<table>\n<tbody>\n<tr>\n<td>Published on Web Code Geeks with permission by Yanis Triandaphilov, partner at our <a href=\"\/\/www.webcodegeeks.com\/join-us\/wcg\/\" target=\"_blank\" rel=\"noopener\">WCG program<\/a>. See the original article here: <a href=\"https:\/\/blog.codeship.com\/build-sms-groceries-app-ionic-angular\/\" target=\"_blank\" rel=\"noopener\">Build an SMS Groceries App with Ionic and Angular<\/a><\/p>\n<p>Opinions expressed by Web Code Geeks contributors are their own.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>In this article, we\u2019re going to have a closer look at the Ionic Framework, which is a modern WEB-based platform for building mobile apps. That means you don\u2019t need to have any knowledge about the mobile platforms to build real apps. Ionic is a full platform which evolved from a simple UI library. It\u2019s a &hellip;<\/p>\n","protected":false},"author":227,"featured_media":909,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[25],"tags":[187],"class_list":["post-22442","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-angular-js","tag-ionic"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Build an SMS Groceries App with Ionic and Angular - Web Code Geeks - 2026<\/title>\n<meta name=\"description\" content=\"Interested to learn more about Ionic? Then check out our article where we Build an SMS Groceries App with Ionic and Angular!\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/sms-groceries-app-ionic-angular\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Build an SMS Groceries App with Ionic and Angular - Web Code Geeks - 2026\" \/>\n<meta property=\"og:description\" content=\"Interested to learn more about Ionic? Then check out our article where we Build an SMS Groceries App with Ionic and Angular!\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/sms-groceries-app-ionic-angular\/\" \/>\n<meta property=\"og:site_name\" content=\"Web Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/webcodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2018-08-23T09:15:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/angularjs-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Yanis Triandaphilov\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@webcodegeeks\" \/>\n<meta name=\"twitter:site\" content=\"@webcodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Yanis Triandaphilov\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"14 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/sms-groceries-app-ionic-angular\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/sms-groceries-app-ionic-angular\/\"},\"author\":{\"name\":\"Yanis Triandaphilov\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/556c1e47406608dd65cbdbc1217575c1\"},\"headline\":\"Build an SMS Groceries App with Ionic and Angular\",\"datePublished\":\"2018-08-23T09:15:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/sms-groceries-app-ionic-angular\/\"},\"wordCount\":1706,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/sms-groceries-app-ionic-angular\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/angularjs-logo.jpg\",\"keywords\":[\"Ionic\"],\"articleSection\":[\"Angular.js\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/sms-groceries-app-ionic-angular\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/sms-groceries-app-ionic-angular\/\",\"url\":\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/sms-groceries-app-ionic-angular\/\",\"name\":\"Build an SMS Groceries App with Ionic and Angular - Web Code Geeks - 2026\",\"isPartOf\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/sms-groceries-app-ionic-angular\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/sms-groceries-app-ionic-angular\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/angularjs-logo.jpg\",\"datePublished\":\"2018-08-23T09:15:00+00:00\",\"description\":\"Interested to learn more about Ionic? Then check out our article where we Build an SMS Groceries App with Ionic and Angular!\",\"breadcrumb\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/sms-groceries-app-ionic-angular\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/sms-groceries-app-ionic-angular\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/sms-groceries-app-ionic-angular\/#primaryimage\",\"url\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/angularjs-logo.jpg\",\"contentUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/angularjs-logo.jpg\",\"width\":150,\"height\":150},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/sms-groceries-app-ionic-angular\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.webcodegeeks.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"JavaScript\",\"item\":\"https:\/\/www.webcodegeeks.com\/category\/javascript\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Angular.js\",\"item\":\"https:\/\/www.webcodegeeks.com\/category\/javascript\/angular-js\/\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Build an SMS Groceries App with Ionic and Angular\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#website\",\"url\":\"https:\/\/www.webcodegeeks.com\/\",\"name\":\"Web Code Geeks\",\"description\":\"Web Developers Resource Center\",\"publisher\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.webcodegeeks.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\/\/www.webcodegeeks.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png\",\"contentUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/webcodegeeks\",\"https:\/\/x.com\/webcodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/556c1e47406608dd65cbdbc1217575c1\",\"name\":\"Yanis Triandaphilov\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/7b336d9c2bb6f83299994032828d8717bae760e864c4ddd75f1b02e61ceed860?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/7b336d9c2bb6f83299994032828d8717bae760e864c4ddd75f1b02e61ceed860?s=96&d=mm&r=g\",\"caption\":\"Yanis Triandaphilov\"},\"description\":\"Yanis Triandaphilov lives and works in Prague. He's been into Ruby and JavaScript development for more than six years now. \\\"Being not too smart, I struggle for clarity and simplicity in everything I do.\\\"\",\"url\":\"https:\/\/www.webcodegeeks.com\/author\/yanis-triandaphilov\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Build an SMS Groceries App with Ionic and Angular - Web Code Geeks - 2026","description":"Interested to learn more about Ionic? Then check out our article where we Build an SMS Groceries App with Ionic and Angular!","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:\/\/www.webcodegeeks.com\/javascript\/angular-js\/sms-groceries-app-ionic-angular\/","og_locale":"en_US","og_type":"article","og_title":"Build an SMS Groceries App with Ionic and Angular - Web Code Geeks - 2026","og_description":"Interested to learn more about Ionic? Then check out our article where we Build an SMS Groceries App with Ionic and Angular!","og_url":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/sms-groceries-app-ionic-angular\/","og_site_name":"Web Code Geeks","article_publisher":"https:\/\/www.facebook.com\/webcodegeeks","article_published_time":"2018-08-23T09:15:00+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/angularjs-logo.jpg","type":"image\/jpeg"}],"author":"Yanis Triandaphilov","twitter_card":"summary_large_image","twitter_creator":"@webcodegeeks","twitter_site":"@webcodegeeks","twitter_misc":{"Written by":"Yanis Triandaphilov","Est. reading time":"14 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/sms-groceries-app-ionic-angular\/#article","isPartOf":{"@id":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/sms-groceries-app-ionic-angular\/"},"author":{"name":"Yanis Triandaphilov","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/556c1e47406608dd65cbdbc1217575c1"},"headline":"Build an SMS Groceries App with Ionic and Angular","datePublished":"2018-08-23T09:15:00+00:00","mainEntityOfPage":{"@id":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/sms-groceries-app-ionic-angular\/"},"wordCount":1706,"commentCount":0,"publisher":{"@id":"https:\/\/www.webcodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/sms-groceries-app-ionic-angular\/#primaryimage"},"thumbnailUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/angularjs-logo.jpg","keywords":["Ionic"],"articleSection":["Angular.js"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/sms-groceries-app-ionic-angular\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/sms-groceries-app-ionic-angular\/","url":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/sms-groceries-app-ionic-angular\/","name":"Build an SMS Groceries App with Ionic and Angular - Web Code Geeks - 2026","isPartOf":{"@id":"https:\/\/www.webcodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/sms-groceries-app-ionic-angular\/#primaryimage"},"image":{"@id":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/sms-groceries-app-ionic-angular\/#primaryimage"},"thumbnailUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/angularjs-logo.jpg","datePublished":"2018-08-23T09:15:00+00:00","description":"Interested to learn more about Ionic? Then check out our article where we Build an SMS Groceries App with Ionic and Angular!","breadcrumb":{"@id":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/sms-groceries-app-ionic-angular\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/sms-groceries-app-ionic-angular\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/sms-groceries-app-ionic-angular\/#primaryimage","url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/angularjs-logo.jpg","contentUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/angularjs-logo.jpg","width":150,"height":150},{"@type":"BreadcrumbList","@id":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/sms-groceries-app-ionic-angular\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.webcodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"JavaScript","item":"https:\/\/www.webcodegeeks.com\/category\/javascript\/"},{"@type":"ListItem","position":3,"name":"Angular.js","item":"https:\/\/www.webcodegeeks.com\/category\/javascript\/angular-js\/"},{"@type":"ListItem","position":4,"name":"Build an SMS Groceries App with Ionic and Angular"}]},{"@type":"WebSite","@id":"https:\/\/www.webcodegeeks.com\/#website","url":"https:\/\/www.webcodegeeks.com\/","name":"Web Code Geeks","description":"Web Developers Resource Center","publisher":{"@id":"https:\/\/www.webcodegeeks.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.webcodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.webcodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.webcodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/webcodegeeks","https:\/\/x.com\/webcodegeeks"]},{"@type":"Person","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/556c1e47406608dd65cbdbc1217575c1","name":"Yanis Triandaphilov","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/7b336d9c2bb6f83299994032828d8717bae760e864c4ddd75f1b02e61ceed860?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/7b336d9c2bb6f83299994032828d8717bae760e864c4ddd75f1b02e61ceed860?s=96&d=mm&r=g","caption":"Yanis Triandaphilov"},"description":"Yanis Triandaphilov lives and works in Prague. He's been into Ruby and JavaScript development for more than six years now. \"Being not too smart, I struggle for clarity and simplicity in everything I do.\"","url":"https:\/\/www.webcodegeeks.com\/author\/yanis-triandaphilov\/"}]}},"_links":{"self":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts\/22442","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/users\/227"}],"replies":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/comments?post=22442"}],"version-history":[{"count":0,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts\/22442\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/media\/909"}],"wp:attachment":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/media?parent=22442"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/categories?post=22442"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/tags?post=22442"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}