How to write data to a file using ngCordova?

@willy_wonga maybe it’s time you put your code in a codepen. Or supply some code.

Thanks for your timely responses, @pcr
On the emulator, my code works well with the plugin.

Here’s my code:
//app.js

angular.module('starter', ['ionic', 'ngCordova', 'starter.controllers', 'starter.services'])

.run(function($ionicPlatform) {
  $ionicPlatform.ready(function() {
    // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
    // for form inputs)
    if (window.cordova && window.cordova.plugins.Keyboard) {
      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
    }
    if (window.StatusBar) {
      // org.apache.cordova.statusbar required
      StatusBar.styleDefault();
    }
  });
})

.config(function($stateProvider, $urlRouterProvider) {

  $stateProvider

  // setup an abstract state for the tabs directive
    .state('tab', {
    url: "/tab",
    abstract: true,
    templateUrl: "templates/tabs.html"
  })

  .state('tab.dash', {
    url: '/dash',
    views: {
      'tab-dash': {
        templateUrl: 'templates/tab-dash.html',
        controller: 'DashCtrl'
      }
    }
  })
  $urlRouterProvider.otherwise('/tab/dash');

});
//controllers.js
angular.module('starter.controllers', [])
.controller('DashCtrl', function($scope, $timeout, $ionicModal, Surveys, Notes, $ionicSideMenuDelegate, $http, $cordovaFile, $ionicPlatform) {
  $scope.surveys = [];
  $scope.selectedStations = null;
  $scope.stations = [];
  $scope.mySelectedStation;
  var date = new Date();
  $scope.date = date;
  $scope.startSurvey = function(station) {
    station.train_arrive1 = new Date();
  };

  var createSurvey = function(survey) {
    var newSurvey = Surveys.newSurvey(survey);
    $scope.surveys.push(newSurvey);
    Surveys.save($scope.surveys);
    $scope.selectSurvey(newSurvey, $scope.surveys.length-1);
    $ionicPlatform.ready(function() {
      alert('cordova.file.dataDirectory: ' + cordova); //I get [object Object]
      alert('cordova.file.dataDirectory: ' + cordova.file.dataDirectory); // I get file is undefined
        $cordovaFile.writeFile(cordova.file.dataDirectory, 'surveys.json', $scope.surveys, true).then(function(result){
          alert('Success! Survey created!');
        }, function(err) {
          console.log("ERROR");
        })
      });  
  }

  $scope.newSurvey = function(survey) {
    createSurvey(survey);
  };
})

//services.js
angular.module('starter.services', [])
.factory('Surveys', function() {
  var surveys = [{}];
  var i = 1; 
  return {
    all: function() {
      var surveyString = window.localStorage['surveys'];
      if(surveyString) {
        return angular.fromJson(surveyString);
      }
      return [];
    },
    save: function(surveys) {
      window.localStorage['surveys'] = angular.toJson(surveys);
    },
    newSurvey: function(survey) {
      return {
        survey_id: i++,
        station_name: survey.stationName,
        line: survey.line,
        time: survey.time,
        direction: survey.direction,
        element_id: survey.elementID,
        component_id: survey.componentID,
        surveyor: survey.surveyor,
        notes: survey.dashNote,
      };
    },
    get: function(surveyId) {
      return surveys[surveyId];
    },
    getLastActiveIndex: function() {
      return parseInt(window.localStorage['lastActiveSurvey']) || 0;
    },
    setLastActiveIndex: function(index) {
      window.localStorage['lastActiveSurvey'] = index;
    }
  } 
})

//index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
    <title></title>

    <link href="lib/ionic/css/ionic.css" rel="stylesheet">
    <link href="css/style.css" rel="stylesheet">
    <script src="lib/ionic/js/ionic.bundle.js"></script>
    <script src="lib/ngCordova/dist/ng-cordova.js"></script>
    <script src="cordova.js"></script>
    <script src="js/app.js"></script>
    <script src="js/controllers.js"></script>
    <script src="js/services.js"></script>
  </head>
  <body ng-app="starter">
    <ion-nav-view></ion-nav-view>
     <ion-nav-bar class="bar-stable">
      <ion-nav-back-button>
      </ion-nav-back-button>
    </ion-nav-bar>
  </body>
</html>

Thanks again for your time and help!

@eno Thanks for your reply!

I believe I’ve installed the plugin because when I run command “ionic plugin list” I get:
cordova-plugin-device 1.0.0 "Device"
org.apache.cordova.file 1.3.0 “File”

I’m not sure if the plugin was injected. How would I check that?
Inside my platforms/android/assets/www/js directory, I see my JS files.
Inside my platforms/android/src/org/apache/cordova directory, I see both the “device” and “file” directories.

Any additional help would be greatly appreciated - thanks!

When I say injected, I mean in your code, i.e. whatever controller/service needs to use it - it should be injected the same way as any other Angular dependency is.

Why do you have $ionicPlatform.ready inside your function? If your intent is to only let the function run after that event has fired, you should wrap it around the function. Ie

$ionicPlatform.ready(function() { 
   var createSurvey  = function(survey) {
   ....
  };

});

I’m not saying this is the cause of your issue, but it’s something I’d change.

Version 1.3 of the File plugin is old. It should be 2. Remove it and then do

cordova plugin add cordova-plugin-file

Fellow Ionic enthusiasts -

I appreciate all the assistance and suggestions on how to fix my plugin issues so far. I’ve been stuck trying to figure out why my app does not correctly utilize cordova’s file plugin. The file plugin works as expected on the android emulator, but would behave as expected on my Samsung tablet. I’ve emailed/stalked several community members ( @pcr, @raymondcamden, @mhartington ) and while I absolutely appreciate their time and effort, I am still unable to get the file plugin to work. When I run the alert: document.addEventListener('deviceready', function () { alert('cordova.plugins are: ' + cordova.plugins); I get cordova.plugins are: undefined. I’ve scoured the web and have tried all the suggestions on this thread. Please if anyone can offer assistance, I will be forever grateful. My code is here: How to write data to a file using ngCordova?

Now, I’m considering whether to write a module that uses Android’s built-in file functions ( https://developer.android.com/training/basics/data-storage/files.html ), which leads me to this question: is it possible to integrate Ionic with native Java code?

Thank you in advance!
Will

In fact the ngCordova plugin is an interface between javascript and native Java functions. Please try following example. This is a very simple and working ionic app.

If this is not what you are looking, let me know. I’ve build a dozen functions that do all kind of Filesystem tasks.
Please let me know step by step what you want.

Thanks for replying. I followed the tutorial step-by-step from the link you posted. I built a new app, and uploaded it to Ionic View. I am getting similar issues. I can see the directories and files in the Android emulator, but I can’t see the filesystem on the device. I am getting the “Ionic Blank Starter” in the header, and a blank screen underneath it. I would show you the logcat, but the device monitor in my Android Studio keeps crashing.

What I am trying to accomplish is to be able to create a file, write to it, and save it on my tablet. Can there be a permissions issue?

@pcr Or is it because I’m using “Ionic View” to load my app?

Yes I thinking So. Ionic view runs in a regular browser. For Cordova plug-ins you must run the app on a device or emulator that supports plug-ins.

Thank you so much @pcr! Your guidance to https://blog.nraboy.com/2014/09/manage-files-in-android-and-ios-using-ionicframework/ through https://www.airpair.com/ionic-framework/posts/ionic-file-browser-app, as well as your sample code, helped me solve the issue I was having with the file plugin. I had been stuck on it for weeks, and I wholeheartedly appreciate your help. Thanks again!

How do you put this in a function for the $scope to use? I am trying to use this code

     $scope.save = function() {
            var inspection = JSON.stringify($scope.inspection);
            $cordovaFile.writeFile(cordova.file.dataDirectory, 'myFile.txt', inspection)
                .then(function(success){
                    alert('file created');
                    
                }, function(error){
                    alert('did not create file ' + error.code);
                });
        };

But it’s not working… Is this correct syntax?

How do you put this in a function for the $scope to use? I am trying to use this code

 $scope.save = function() {
        var inspection = JSON.stringify($scope.inspection);
        $cordovaFile.writeFile(cordova.file.dataDirectory, 'myFile.txt', inspection)
            .then(function(success){
                alert('file created');
                
            }, function(error){
                alert('did not create file ' + error.code);
            });
    };

But it’s not working… Is this correct syntax?

How do you know it’s not working? Error, messages

That’s the hard part, there are no console errors and the alerts are not working. It’s like the writeFile function isn’t firing at all. If I add an alert outside of the cordova callback, but still inside the save function, that alert fires. So, basically when the button is clicked, nothing happens. No success, no error, nothing.

However, If I change the file path to something that will break it on purpose, like “0” <-- not a valid path. THEN the error callback is triggered. So, it’s working sometimes but only if there’s an error. I’m testing on my iOS emulator, Android emulator, and my Android phone as well. All 3 have the same issues.

I still have yet to see a code example of a controller that creates a function that triggers the file to be saved like my code example.

OK, I think I fixed it but I don’t know why this would work. I took the functions OUT of the device.ready function and now I can use them like this:

      document.addEventListener("deviceready", function () {

        var device = $cordovaDevice.getDevice();

        var cordova = $cordovaDevice.getCordova();

        var model = $cordovaDevice.getModel();

        var platform = $cordovaDevice.getPlatform();

        var uuid = $cordovaDevice.getUUID();

        $scope.deviceID = $cordovaDevice.getUUID();

        $cordovaFile.getFreeDiskSpace()
            .then(function (success) {
             // success in kilobytes
             $scope.freeSpace = success;
            }, function (error) {
              // error
              $scope.freeSpace = 'did not get free space...';
            });

        var version = $cordovaDevice.getVersion();

      }, false);  //end device ready

        $scope.save = function() {
            $cordovaVibration.vibrate(1000);
            var inspection = JSON.stringify($scope.inspection);
            $cordovaFile.writeFile(cordova.file.dataDirectory, 'myFile.txt', inspection, true)
                .then(function(success){
                  
                    alert(JSON.parse(inspection));
                }, function(error){
                    alert('did not create file ' + error.code);
                });
        };


        $scope.read = function() {
            $cordovaFile.checkFile(cordova.file.dataDirectory, 'myFile.txt')
                .then(function(success) {
                    alert('found it!');

                }, function(error){
                    alert('didn\'t find the file: ' + error.code);
                })
        };
1 Like

Any Hints if cordova.file.dataDirectory is undefined on ios 7.1.2?

Used the cordova-plugin-file - Plugin and it words on android, but not on ios.

Any ideas?

How to write file in ionic 2?
Can anyone provide working example. Thanks in advance.