{"id":489,"date":"2015-11-11T15:00:00","date_gmt":"2015-11-11T15:00:00","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/"},"modified":"2015-11-11T15:00:00","modified_gmt":"2015-11-11T15:00:00","slug":"cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/ko\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/","title":{"rendered":"Cross Platform Storage and Sync with Ionic Framework, Couchbase, and PouchDB"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Ionic Framework is still one of the leaders in hybrid mobile application development. It allows you to create Android and iOS applications<br>\nusing only HTML, JavaScript, and CSS.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Previously I wrote about how to use <a href=\"https:\/\/www.couchbase.com\/blog\/using-couchbase-in-your-ionic-framework-application-part-1\/\">Couchbase in<br>\nan Ionic Framework mobile Android and iOS application<\/a>, but it made use of Couchbase<br>\nLite as its embedded NoSQL database. This time around we&#8217;re going to look at replacing Couchbase Lite with PouchDB. Should you use one<br>\nmethod over the other? No, it comes down to preference in the end.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you haven&#8217;t already seen my post regarding <a href=\"https:\/\/www.couchbase.com\/blog\/sync-with-couchbase-using-only-angularjs-and-pouchdb\/\">PouchDB<br>\nand AngularJS with Couchbase<\/a>, I encourage you to have a look as this tutorial will be using many of the same concepts and code.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What We&#8217;ll Need<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">There are a few requirements to the application we&#8217;re going to build. We&#8217;ll see how to obtain them along the way, but here is a<br>\ntaste so you know what you&#8217;re getting yourself into.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Couchbase Sync Gateway<\/li>\n\n\n<li>PouchDB 4<\/li>\n\n\n<li>Ionic Framework 1<\/li>\n\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Getting the Couchbase Sync Gateway<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">This project will require the Couchbase Sync Gateway in order to succeed. If you&#8217;re unfamiliar, the Couchbase Sync Gateway is a<br>\nmiddleman service that handles processing data between the local application (your Ionic Framework application) and the Couchbase Server. We<br>\nwon&#8217;t be using Couchbase Server in this example so the Sync Gateway will act as our in-memory storage solution in the cloud.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The Couchbase Sync Gateway can be found via the <a href=\"https:\/\/www.couchbase.com\/nosql-databases\/downloads\/\">Couchbase downloads section<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Creating Our Ionic Framework Project<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Before going any further it is good to note that if you&#8217;re not using a Mac, you cannot add and build for the iOS platform. Windows, Mac,<br>\nand Linux computers can build for Android, but only Mac can build for iOS.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">From the Command Prompt (Windows) or Terminal (Mac and Linux), execute the following command to create a new Ionic Framework project:<\/p>\n\n\n<p>[crayon lang=&#8221;bash&#8221;]<br \/>\nionic start PouchProject blank<br \/>\ncd PouchProject<br \/>\nionic platform add android<br \/>\nionic platform add ios<br \/>\n[\/crayon]<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Our blank template project is now ready for working with.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Including The Dependencies<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">If you haven&#8217;t already, <a href=\"https:\/\/www.pouchdb.com\/\">download PouchDB 4<\/a> and make note of the <strong>min.js<\/strong> file as<br>\nwe&#8217;ll be using it through the project. Copy the<br>\nPouchDB <strong>min.js<\/strong> file into your Ionic project&#8217;s <strong>www\/js<\/strong> directory.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">With the file in place, open your project&#8217;s <strong>www\/index.html<\/strong> file and include the following:<\/p>\n\n\n<p>[crayon lang=&#8221;html&#8221;]<\/p>\n<p>[\/crayon]<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This script line should appear above the <strong>app.js<\/strong> include line and the version information should match that of your actual<br>\nfile rather than the version I included here.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Modifying The Index File<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Before we jump into the AngularJS code we need to make a final revision to the project&#8217;s <strong>www\/index.html<\/strong> file. Open it and<br>\nreplace the tags with the following:<\/p>\n\n\n<p>[crayon lang=&#8221;html&#8221;]<\/p>\n<p>[\/crayon]<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Because we&#8217;re using the AngularJS UI-Router that ships with Ionic Framework, we only need a basic <strong>www\/index.html<\/strong> file.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Creating Our PouchDB AngularJS Service<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Before we start using PouchDB, we need to make a wrapper for it so it fits nicely with AngularJS and Ionic Framework. Out of the box PouchDB<br>\nis a vanilla JavaScript library, so it isn&#8217;t necessarily the easiest to use when it comes to AngularJS.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Inside your project&#8217;s <strong>www\/js\/app.js<\/strong> file, include the following service code:<\/p>\n\n\n<p>[crayon lang=&#8221;javascript&#8221;]<br \/>\n.service(&#8220;$pouchDB&#8221;, [&#8220;$rootScope&#8221;, &#8220;$q&#8221;, function($rootScope, $q) {<\/p>\n<p>    var database;<br \/>\n    var changeListener;<\/p>\n<p>    this.setDatabase = function(databaseName) {<br \/>\n        database = new PouchDB(databaseName);<br \/>\n    }<\/p>\n<p>    this.startListening = function() {<br \/>\n        changeListener = database.changes({<br \/>\n            live: true,<br \/>\n            include_docs: true<br \/>\n        }).on(&#8220;change&#8221;, function(change) {<br \/>\n            if(!change.deleted) {<br \/>\n                $rootScope.$broadcast(&#8220;$pouchDB:change&#8221;, change);<br \/>\n            } else {<br \/>\n                $rootScope.$broadcast(&#8220;$pouchDB:delete&#8221;, change);<br \/>\n            }<br \/>\n        });<br \/>\n    }<\/p>\n<p>    this.stopListening = function() {<br \/>\n        changeListener.cancel();<br \/>\n    }<\/p>\n<p>    this.sync = function(remoteDatabase) {<br \/>\n        database.sync(remoteDatabase, {live: true, retry: true});<br \/>\n    }<\/p>\n<p>    this.save = function(jsonDocument) {<br \/>\n        var deferred = $q.defer();<br \/>\n        if(!jsonDocument._id) {<br \/>\n            database.post(jsonDocument).then(function(response) {<br \/>\n                deferred.resolve(response);<br \/>\n            }).catch(function(error) {<br \/>\n                deferred.reject(error);<br \/>\n            });<br \/>\n        } else {<br \/>\n            database.put(jsonDocument).then(function(response) {<br \/>\n                deferred.resolve(response);<br \/>\n            }).catch(function(error) {<br \/>\n                deferred.reject(error);<br \/>\n            });<br \/>\n        }<br \/>\n        return deferred.promise;<br \/>\n    }<\/p>\n<p>    this.delete = function(documentId, documentRevision) {<br \/>\n        return database.remove(documentId, documentRevision);<br \/>\n    }<\/p>\n<p>    this.get = function(documentId) {<br \/>\n        return database.get(documentId);<br \/>\n    }<\/p>\n<p>    this.destroy = function() {<br \/>\n        database.destroy();<br \/>\n    }<\/p>\n<p>}])<br \/>\n[\/crayon]<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You might be thinking that code looks familiar. Well, it is the exact code I used in<br>\nthe <a href=\"https:\/\/www.couchbase.com\/blog\/sync-with-couchbase-using-only-angularjs-and-pouchdb\/\">previous PouchDB example for AngularJS<\/a>.<br>\nNow we can easily use PouchDB in our project.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Creating A Local Database And Start Syncing<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The goal here is to create a local database when our application starts (if it doesn&#8217;t already exist) and then start syncing with the<br>\nCouchbase Sync Gateway. This can be accomplished in the AngularJS <strong>run()<\/strong> function of our <strong>www\/js\/app.js<\/strong><br>\nfile:<\/p>\n\n\n<p>[crayon lang=&#8221;javascript&#8221;]<br \/>\n.run(function($ionicPlatform, $pouchDB) {<br \/>\n    $ionicPlatform.ready(function() {<br \/>\n        if(window.cordova &#038;&#038; window.cordova.plugins.Keyboard) {<br \/>\n            cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);<br \/>\n        }<br \/>\n        if(window.StatusBar) {<br \/>\n            StatusBar.styleDefault();<br \/>\n        }<br \/>\n    });<br \/>\n    $pouchDB.setDatabase(&#8220;nraboy-test&#8221;);<br \/>\n    if(ionic.Platform.isAndroid()) {<br \/>\n        $pouchDB.sync(&#8220;https:\/\/192.168.57.1:4984\/test-database&#8221;);<br \/>\n    } else {<br \/>\n        $pouchDB.sync(&#8220;https:\/\/localhost:4984\/test-database&#8221;);<br \/>\n    }<br \/>\n})<br \/>\n[\/crayon]<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The IP addresses I used might vary for you in terms of simulators, but for production they will likely match for both iOS and<br>\nAndroid.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Designing A Controller For Your Views<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">We haven&#8217;t created our views yet, but let&#8217;s go ahead and create the controller logic for them. Open your project&#8217;s<br>\n<strong>www\/js\/app.js<\/strong> file and include the following controller:<\/p>\n\n\n<p>[crayon lang=&#8221;javascript&#8221;]<br \/>\n.controller(&#8220;MainController&#8221;, function($scope, $rootScope, $state, $stateParams, $ionicHistory, $pouchDB) {<\/p>\n<p>    $scope.items = {};<\/p>\n<p>    $scope.save = function(firstname, lastname, email) { }<\/p>\n<p>    $scope.delete = function(id, rev) { }<\/p>\n<p>    $scope.back = function() { }<\/p>\n<p>})<br \/>\n[\/crayon]<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">As of right now we have a basic controller. We know we&#8217;ll be saving and deleting items which is why we&#8217;ve defined a function for such<br>\ntasks. We also have a function called <strong>back()<\/strong> that will pop an item (go back) in the history stack.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s go bottom up and start with the <strong>back()<\/strong> function. It should contain the following code:<\/p>\n\n\n<p>[crayon lang=&#8221;javascript&#8221;]<br \/>\n$scope.back = function() {<br \/>\n    $ionicHistory.goBack();<br \/>\n}<br \/>\n[\/crayon]<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">When it comes to deleting items from the database we&#8217;ll need to provide a particular document id to delete as well as the particular revision<br>\nwe wish to delete. This will all be passed from the views, but the logic will be as follows:<\/p>\n\n\n<p>[crayon lang=&#8221;javascript&#8221;]<br \/>\n$scope.delete = function(id, rev) {<br \/>\n    $pouchDB.delete(id, rev);<br \/>\n}<br \/>\n[\/crayon]<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The <strong>delete(id, rev)<\/strong> function makes a call to the PouchDB service that we made.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This leaves us with the <strong>save()<\/strong> function. Based on the simplicity of our application we&#8217;ll only be saving three data<br>\nproperties, but it can easily be changed should you need to. Inside your controller, make the <strong>save()<\/strong> function like so:<\/p>\n\n\n<p>[crayon lang=&#8221;javascript&#8221;]<br \/>\n$scope.save = function(firstname, lastname, email) {<br \/>\n    var jsonDocument = {<br \/>\n        &#8220;firstname&#8221;: firstname,<br \/>\n        &#8220;lastname&#8221;: lastname,<br \/>\n        &#8220;email&#8221;: email<br \/>\n    };<br \/>\n    if($stateParams.documentId) {<br \/>\n        jsonDocument[&#8220;_id&#8221;] = $stateParams.documentId;<br \/>\n        jsonDocument[&#8220;_rev&#8221;] = $stateParams.documentRevision;<br \/>\n    }<br \/>\n    $pouchDB.save(jsonDocument).then(function(response) {<br \/>\n        $state.go(&#8220;list&#8221;);<br \/>\n    }, function(error) {<br \/>\n        console.log(&#8220;ERROR -> &#8221; + error);<br \/>\n    });<br \/>\n}<br \/>\n[\/crayon]<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This function does two things. It will prepare an insert or it will prepare an update should a document id and document revision<br>\nbe available.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We&#8217;re not quite done yet though. Although we finished all our functions, we still need to handle listening for<br>\nchanges. When we call <strong>$pouchDB.startListening();<\/strong> in our controller, our PouchDB service will start making use of the<br>\nAngularJS <strong>$broadcast<\/strong>. While it is broadcasting we can listen for those broadcasts using something like:<\/p>\n\n\n<p>[crayon lang=&#8221;javascript&#8221;]<br \/>\n$rootScope.$on(&#8220;$pouchDB:change&#8221;, function(event, data) {<br \/>\n    $scope.items[data.doc._id] = data.doc;<br \/>\n    $scope.$apply();<br \/>\n});<\/p>\n<p>$rootScope.$on(&#8220;$pouchDB:delete&#8221;, function(event, data) {<br \/>\n    delete $scope.items[data.doc._id];<br \/>\n    $scope.$apply();<br \/>\n});<br \/>\n[\/crayon]<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Our view controller logic is now good to go!<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Defining Your Ionic Framework Views<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The last part of our <strong>www\/js\/app.js<\/strong> file will be for defining our views. This is done in the AngularJS<br>\n<strong>config()<\/strong> function like so:<\/p>\n\n\n<p>[crayon lang=&#8221;javascript&#8221;]<br \/>\n.config(function($stateProvider, $urlRouterProvider) {<br \/>\n    $stateProvider<br \/>\n        .state(&#8220;list&#8221;, {<br \/>\n            &#8220;url&#8221;: &#8220;\/list&#8221;,<br \/>\n            &#8220;templateUrl&#8221;: &#8220;templates\/list.html&#8221;,<br \/>\n            &#8220;controller&#8221;: &#8220;MainController&#8221;<br \/>\n        })<br \/>\n        .state(&#8220;item&#8221;, {<br \/>\n            &#8220;url&#8221;: &#8220;\/item\/:documentId\/:documentRevision&#8221;,<br \/>\n            &#8220;templateUrl&#8221;: &#8220;templates\/item.html&#8221;,<br \/>\n            &#8220;controller&#8221;: &#8220;MainController&#8221;<br \/>\n        });<br \/>\n    $urlRouterProvider.otherwise(&#8220;list&#8221;);<br \/>\n})<br \/>\n[\/crayon]<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We defined two views, one for all our list items and one for creating and updating new list items. The <strong>item<\/strong> state takes an optional<br>\ndocument id and document revision parameter. When they are present, it means we are going to be updating a particular document.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">All our AngularJS logic is complete now. We have initialized our database, started syncing, defined our views, and planned for interaction<br>\nfrom our views.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Creating A List View<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Here we will define how data is presented in the list. In your project&#8217;s <strong>www\/templates\/list.html<\/strong> file, add the following code:<\/p>\n\n\n<p>[crayon lang=&#8221;html&#8221;]<\/p>\n<p>                {{value.firstname}} {{value.lastname}}<\/p>\n<p>[\/crayon]<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">When swiping a list item we are presented with a delete button that will call the <strong>delete()<\/strong> function of our controller.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Creating A Form View<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Here we will define out documents will be inserted or updated in our database. Essentially, this view is only a form. In your project&#8217;s<br>\n<strong>www\/templates\/item.html<\/strong> file, add the following code:<\/p>\n\n\n\n<label class=\"item item-input\">  <\/label>\n\n\n\n<label class=\"item item-input\">  <\/label>\n\n\n\n<label class=\"item item-input\">  <\/label>\n\n\n\n<p class=\"wp-block-paragraph\">\u00a0<\/p>\n\n\n\n<button class=\"button button-block button-positive\"> Save <\/button>\n\n\n\n<h2 class=\"wp-block-heading\">The Sync Gateway Configuration<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">PouchDB and Ionic Framework are only half the story here. Sure they will create a nice locally running application, but we want things to sync. The Couchbase Sync Gateway is our endpoint for this and of course PouchDB works great with it.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Inside your project&#8217;s <strong>sync-gateway-config.json<\/strong> file, add the following:<\/p>\n\n\n<p>[crayon lang=&#8221;json&#8221;]<br \/>\n{<br \/>\n    &#8220;log&#8221;:[&#8220;CRUD+&#8221;, &#8220;REST+&#8221;, &#8220;Changes+&#8221;, &#8220;Attach+&#8221;],<br \/>\n    &#8220;databases&#8221;: {<br \/>\n        &#8220;test-database&#8221;: {<br \/>\n            &#8220;server&#8221;:&#8221;walrus:data&#8221;,<br \/>\n            &#8220;sync&#8221;:`<br \/>\n                function (doc) {<br \/>\n                    channel (doc.channels);<br \/>\n                }<br \/>\n            `,<br \/>\n            &#8220;users&#8221;: {<br \/>\n                &#8220;GUEST&#8221;: {<br \/>\n                    &#8220;disabled&#8221;: false,<br \/>\n                    &#8220;admin_channels&#8221;: [&#8220;*&#8221;]<br \/>\n                }<br \/>\n            }<br \/>\n        }<br \/>\n    },<br \/>\n    &#8220;CORS&#8221;: {<br \/>\n        &#8220;Origin&#8221;: [&#8220;https:\/\/localhost:9000&#8221;],<br \/>\n        &#8220;LoginOrigin&#8221;: [&#8220;https:\/\/localhost:9000&#8221;],<br \/>\n        &#8220;Headers&#8221;: [&#8220;Content-Type&#8221;],<br \/>\n        &#8220;MaxAge&#8221;: 17280000<br \/>\n    }<br \/>\n}<br \/>\n[\/crayon]<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This is one of the most basic configurations around. A few things to note about it:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>It uses walrus:data for storage which is in memory and does not persist. Not to be used for production.<\/li>\n\n\n<li>All data is synced via the GUEST user, so there is no authentication happening here, but there could be.<\/li>\n\n\n<li>We are fixing CORS issues by allowing requests on localhost:9000 in case you wanted to serve with Python for browser testing.<\/li>\n\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Testing The Application<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">At this point all our code is in place and our Sync Gateway is ready to be run. Start up the Sync Gateway by running the following in a<br>\nCommand Prompt or Terminal:<\/p>\n\n\n<p>[crayon lang=&#8221;bash&#8221;]<br \/>\n\/path\/to\/sync\/gateway\/bin\/sync-gateway \/path\/to\/project\/sync-gateway-config.json<br \/>\n[\/crayon]<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The Sync Gateway should now be running and you can validate this by visiting https:\/\/localhost:4984 in your web browser.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Testing For Android<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">With a device connected or a simulator running, from the Command Prompt or Terminal, run the following two commands to build and<br>\ninstall the APK file:<\/p>\n\n\n<p>[crayon lang=&#8221;bash&#8221;]<br \/>\nionic build android<br \/>\nadb install -r platforms\/android\/build\/outputs\/apk\/android-debug.apk<br \/>\n[\/crayon]<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Testing For iOS<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">There are two good ways to do this. You can either build the project and open it with Xcode, or you can build and<br>\nemulate the application without launching Xcode. The first can be done like so:<\/p>\n\n\n<p>[crayon lang=&#8221;bash&#8221;]<br \/>\nionic build ios<br \/>\n[\/crayon]<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Then open the project&#8217;s platform\/ios\/ directory and launch the Xcode project file.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you&#8217;ve installed the Node Package Manager (NPM) package ios-sim, you can do the following:<\/p>\n\n\n<p>[crayon lang=&#8221;bash&#8221;]<br \/>\nionic build ios<br \/>\nionic emulate ios<br \/>\n[\/crayon]<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">You saw now that there are two ways you can use Couchbase in your Ionic Framework mobile Android and iOS application. You can use the<br>\nApache Cordova Couchbase plugin as demonstrated in<br>\nthe <a href=\"https:\/\/www.couchbase.com\/blog\/using-couchbase-in-your-ionic-framework-application-part-1\/\">previous blog series<\/a>, or you can<br>\nuse PouchDB. Both of these are very suitable options when it comes to cross platform data storage and sync in your application.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You can obtain the full working source code to this blog post via<br>\nour <a href=\"https:\/\/github.com\/couchbaselabs\/ionic-framework-pouchdb\">Couchbase Labs GitHub repository<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Ionic Framework is still one of the leaders in hybrid mobile application development. It allows you to create Android and iOS applications using only HTML, JavaScript, and CSS. Previously I wrote about how to use Couchbase in an Ionic Framework mobile Android and iOS application, but it made use of Couchbase Lite as its embedded [&hellip;]<\/p>\n","protected":false},"author":63,"featured_media":18,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"_acf":"","footnotes":""},"categories":[1],"tags":[164,168,161,166],"ppma_author":[148],"class_list":["post-489","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-angularjs","tag-hybrid","tag-ionic-framework","tag-pouchdb"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.6 (Yoast SEO v27.6) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Sync Couchbase in Ionic Framework and PouchDB<\/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:\/\/www.couchbase.com\/blog\/ko\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/\" \/>\n<meta property=\"og:locale\" content=\"ko_KR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Cross Platform Storage and Sync with Ionic Framework, Couchbase, and PouchDB\" \/>\n<meta property=\"og:description\" content=\"Ionic Framework is still one of the leaders in hybrid mobile application development. It allows you to create Android and iOS applications using only HTML, JavaScript, and CSS. Previously I wrote about how to use Couchbase in an Ionic Framework mobile Android and iOS application, but it made use of Couchbase Lite as its embedded [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/ko\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/thepolyglotdeveloper\" \/>\n<meta property=\"article:published_time\" content=\"2015-11-11T15:00:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/5\/2026\/05\/couchbase-nosql-dbaas.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1800\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Nic Raboy, Developer Advocate, Couchbase\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@nraboy\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Nic Raboy, Developer Advocate, Couchbase\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8\ubd84\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\\\/\"},\"author\":{\"name\":\"Nic Raboy, Developer Advocate, Couchbase\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#\\\/schema\\\/person\\\/bb545ebe83bb2d12f91095811d0a72e1\"},\"headline\":\"Cross Platform Storage and Sync with Ionic Framework, Couchbase, and PouchDB\",\"datePublished\":\"2015-11-11T15:00:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\\\/\"},\"wordCount\":1967,\"commentCount\":28,\"publisher\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/5\\\/2026\\\/05\\\/couchbase-nosql-dbaas.png\",\"keywords\":[\"angularjs\",\"hybrid\",\"ionic framework\",\"pouchdb\"],\"articleSection\":[\"Uncategorized\"],\"inLanguage\":\"ko-KR\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\\\/\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\\\/\",\"name\":\"Sync Couchbase in Ionic Framework and PouchDB\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/5\\\/2026\\\/05\\\/couchbase-nosql-dbaas.png\",\"datePublished\":\"2015-11-11T15:00:00+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\\\/#breadcrumb\"},\"inLanguage\":\"ko-KR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"ko-KR\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/5\\\/2026\\\/05\\\/couchbase-nosql-dbaas.png\",\"contentUrl\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/5\\\/2026\\\/05\\\/couchbase-nosql-dbaas.png\",\"width\":1800,\"height\":630},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Cross Platform Storage and Sync with Ionic Framework, Couchbase, and PouchDB\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/\",\"name\":\"The Couchbase Blog\",\"description\":\"Couchbase, the NoSQL Database\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"ko-KR\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"ko-KR\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/5\\\/2026\\\/06\\\/logo.svg\",\"contentUrl\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/5\\\/2026\\\/06\\\/logo.svg\",\"width\":\"1024\",\"height\":\"1024\",\"caption\":\"The Couchbase Blog\"},\"image\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#\\\/schema\\\/person\\\/bb545ebe83bb2d12f91095811d0a72e1\",\"name\":\"Nic Raboy, Developer Advocate, Couchbase\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"ko-KR\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g8863514d8bed0cf6080f23db40e00354\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g\",\"caption\":\"Nic Raboy, Developer Advocate, Couchbase\"},\"description\":\"Nic Raboy is an advocate of modern web and mobile development technologies. He has experience in Java, JavaScript, Golang and a variety of frameworks such as Angular, NativeScript, and Apache Cordova. Nic writes about his development experiences related to making web and mobile development easier to understand.\",\"sameAs\":[\"https:\\\/\\\/www.thepolyglotdeveloper.com\",\"https:\\\/\\\/www.facebook.com\\\/thepolyglotdeveloper\",\"https:\\\/\\\/x.com\\\/nraboy\"],\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/ko\\\/author\\\/nic-raboy-2\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Sync Couchbase in Ionic Framework and PouchDB","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.couchbase.com\/blog\/ko\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/","og_locale":"ko_KR","og_type":"article","og_title":"Cross Platform Storage and Sync with Ionic Framework, Couchbase, and PouchDB","og_description":"Ionic Framework is still one of the leaders in hybrid mobile application development. It allows you to create Android and iOS applications using only HTML, JavaScript, and CSS. Previously I wrote about how to use Couchbase in an Ionic Framework mobile Android and iOS application, but it made use of Couchbase Lite as its embedded [&hellip;]","og_url":"https:\/\/www.couchbase.com\/blog\/ko\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/","og_site_name":"The Couchbase Blog","article_author":"https:\/\/www.facebook.com\/thepolyglotdeveloper","article_published_time":"2015-11-11T15:00:00+00:00","og_image":[{"width":1800,"height":630,"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/5\/2026\/05\/couchbase-nosql-dbaas.png","type":"image\/png"}],"author":"Nic Raboy, Developer Advocate, Couchbase","twitter_card":"summary_large_image","twitter_creator":"@nraboy","twitter_misc":{"Written by":"Nic Raboy, Developer Advocate, Couchbase","Est. reading time":"8\ubd84"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/"},"author":{"name":"Nic Raboy, Developer Advocate, Couchbase","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/bb545ebe83bb2d12f91095811d0a72e1"},"headline":"Cross Platform Storage and Sync with Ionic Framework, Couchbase, and PouchDB","datePublished":"2015-11-11T15:00:00+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/"},"wordCount":1967,"commentCount":28,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/5\/2026\/05\/couchbase-nosql-dbaas.png","keywords":["angularjs","hybrid","ionic framework","pouchdb"],"articleSection":["Uncategorized"],"inLanguage":"ko-KR","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/","url":"https:\/\/www.couchbase.com\/blog\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/","name":"Sync Couchbase in Ionic Framework and PouchDB","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/5\/2026\/05\/couchbase-nosql-dbaas.png","datePublished":"2015-11-11T15:00:00+00:00","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/#breadcrumb"},"inLanguage":"ko-KR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/"]}]},{"@type":"ImageObject","inLanguage":"ko-KR","@id":"https:\/\/www.couchbase.com\/blog\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/5\/2026\/05\/couchbase-nosql-dbaas.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/5\/2026\/05\/couchbase-nosql-dbaas.png","width":1800,"height":630},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/cross-platform-storage-and-sync-with-ionic-framework-couchbase-and-pouchdb\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Cross Platform Storage and Sync with Ionic Framework, Couchbase, and PouchDB"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"The Couchbase Blog","description":"Couchbase, the NoSQL Database","publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"ko-KR"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"The Couchbase Blog","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"ko-KR","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/5\/2026\/06\/logo.svg","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/5\/2026\/06\/logo.svg","width":"1024","height":"1024","caption":"The Couchbase Blog"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/bb545ebe83bb2d12f91095811d0a72e1","name":"Nic Raboy, Developer Advocate, Couchbase","image":{"@type":"ImageObject","inLanguage":"ko-KR","@id":"https:\/\/secure.gravatar.com\/avatar\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g8863514d8bed0cf6080f23db40e00354","url":"https:\/\/secure.gravatar.com\/avatar\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g","caption":"Nic Raboy, Developer Advocate, Couchbase"},"description":"Nic Raboy is an advocate of modern web and mobile development technologies. He has experience in Java, JavaScript, Golang and a variety of frameworks such as Angular, NativeScript, and Apache Cordova. Nic writes about his development experiences related to making web and mobile development easier to understand.","sameAs":["https:\/\/www.thepolyglotdeveloper.com","https:\/\/www.facebook.com\/thepolyglotdeveloper","https:\/\/x.com\/nraboy"],"url":"https:\/\/www.couchbase.com\/blog\/ko\/author\/nic-raboy-2\/"}]}},"acf":[],"authors":[{"term_id":148,"user_id":63,"is_guest":0,"slug":"nic-raboy-2","display_name":"Nic Raboy, Developer Advocate, Couchbase","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/?s=96&d=mm&r=g","author_category":"","first_name":"Nic","last_name":"Raboy","user_url":"","job_title":"","description":"Nic Raboy is an advocate of modern web and mobile development technologies. He has experience in Java, JavaScript, Golang and a variety of frameworks such as Angular, NativeScript, and Apache Cordova. Nic writes about his development experiences related to making web and mobile development easier to understand."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/posts\/489","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/users\/63"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/comments?post=489"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/posts\/489\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/media\/18"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/media?parent=489"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/categories?post=489"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/tags?post=489"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/ko\/wp-json\/wp\/v2\/ppma_author?post=489"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}