Local Storage & Objects


#1

Hey everyone.

I’m having a little trouble with getting my head around localStorage, and especially the when it comes to dealing with objects. I understand that the guys at Ionic have put together a tutorial on localstorage but it’s the last 10% of what I’m trying to do is failing I believe.

Below, I’m basically trying to initialise an object in a localStorage key called ‘items’. Then when I submit the data from a form I am pushing an object onto the array in ‘keys’. However, while the initalised object is saving to localStorage the createNewContact function is not. Any ideas? Thanks heaps in advance!

window.localStorage['items'] = JSON.stringify([{ 
  title: 'You Owe Me Now',
  fullName: 'Cameron Bourke',
  dollarAmount: '2',
  description: 'You owe me $2 for downloading this app. Only kidding!! This is just an example of a "Theyo". Delete me now by swiping to the left and enjoy.'
}]);

$scope.contacts = JSON.parse(localStorage.getItem('items')) || [];
console.log(window.localStorage['items']);

$scope.createContact = function(u) {     
  $scope.contacts.push({ fullName: u.fullName,
                         title: u.title,
                         dollarAmount: u.dollarAmount,
                         description: u.description });
  u.fullName = '';
  u.title = '';
  u.dollarAmount = '';
  u.description = '';
  $scope.modal.hide();
};

$scope.onItemDelete = function(item) {
  $scope.contacts.splice($scope.contacts.indexOf(item), 1);
};

#2

I believe the problem is in the code you provided, you are not actually saving to localstorage in the $scope.createContact function, which is why the changes don’t persist. You could do something like the following inside the createContact function

window.localstorage['items']=JSON.stringify($scope.contacts);

which should write the contacts to localstorage.


#3

You may want to check out the ngStorage library. It allows you to use local storage without all the JSON.parse and JSON.stringify nonsense.


#4

Or even simpler, one could use a custom angular factory similar to as explained in this article link http://learn.ionicframework.com/formulas/localstorage/

angular.module('ionic.utils', [])

.factory('$localstorage', ['$window', function($window) {
  return {
    set: function(key, value) {
      $window.localStorage[key] = value;
    },
    get: function(key, defaultValue) {
      return $window.localStorage[key] || defaultValue;
    },
    setObject: function(key, value) {
      $window.localStorage[key] = JSON.stringify(value);
    },
    getObject: function(key) {
      return JSON.parse($window.localStorage[key] || '{}');
    }
  }
}]);

#5

+1 for the solution from @sunnyday , I use it and love it, super convenient and bullet proof from my experience.


#6

Currently, I also use $location service as @sunnyday mentioned. The only part where it’s tricky/where it gets me is when the page is refreshed, and then try to add an object to an array, it clears out all the previous objects in that array and then adds it.


#7

Ok… so I have page with a ion-list that gets populated from a JSON…

I want to use ActionSheet in order to run a function that adds the current item selected ( by tap and hold on it ) to another array. That array will be displayed also in the list but under a new which will add a new item-divider div. My problem is that using this code is adding to the array only undefined items:

angular.module('starter.controllers', ['ionic'])
// Get item list	
.controller('ItemsCtrl', ['$scope', 'Items', '$ionicActionSheet', function($scope, Items, $ionicActionSheet){
	    $scope.items = [];
$scope.getAll = function() {
        
		    Items.getAll().then(function (items) {
		      $scope.items = items;
$scope.favorite = [];
 $scope.addFavorite = function (fav){

   $scope.newFav = fav;
    console.log($scope.favorite); // undefined ????
   $scope.favorite.push($scope.newFav);
    console.log($scope.favorite); 

};           
$scope.Optiuni = function() {

   // Show the action sheet
   var hideSheet = $ionicActionSheet.show({
     buttons: [
       { text: 'Add to favorite' }
     ],
 
 titleText: 'Optiuni',
 cancelText: 'Cancel',
 cancel: function() {
      // add cancel code..
    },
 buttonClicked: function(index) {
   if(index == 0) {
      $scope.addFavorite($scope.items[i]);
        
   }
     return true;
 }

 });
    }

I think my problem here is how can I define the current item that was tapped and hold on. Here:

$scope.addFavorite($scope.items[i]);

I may also want this favorite items to be available after app restart… how should I use localstorage for this? Or should I relay on view cache?
Any help will be much appreciated.

Thank you and Merry Christmas to everyone!


#8

I would suggest the best bet would be to use it through service. Create your empty array in service and call it from the controller whenever you need it. To retain the values, you will need local storage, and Ionic has an example in it’s formulas: http://learn.ionicframework.com/formulas/localstorage/

Hope that helps a bit.


#9

Yes I already figured it out… it was a problem of logic in my code.

Thank you for reply.


#10

I do the same thing in my project, except I added setObject and getObject to the Storage.prototype


#11

Hello forumgoers,

I am trying to use a similar thing in an app I am building. In short, I want users to set some settings on one view “setup”, and then have those settings control a $timeout that occurs in the next view, which is called “photographing”.

I’m actually not completely positive that I need local storage for this, but I think I’m in the right place.

setup.js:

    <ion-view view-title="setup" ng-init="durVal = '60'; freqVal = '5';">
  <ion-content>
    <!-- <ion-list>
      <ion-item ng-repeat="playlist in playlists" href="#/app/playlists/{{playlist.id}}">
        {{playlist.title}}
      </ion-item>
    </ion-list> -->
    <center>
    <img src="img/hourglassSetup.svg" width = 300 id="hourglassSetup"></img>
    </center>
    <div class="list">
	  <div class="item range range-positive">
	    <i class="icon ion-clock"></i>
	    <p class="sideMenuLabel">duration</p>
	    <input id = "duration" type="range" name="volume" min="30" max="90" value="{{durVal}}" ng-model="durVal">
	    <p id="sliderValue">{{durVal}} min</p>
	  </div>
	  <div class="item range range-positive">
	    <i class="icon ion-speedometer"></i>
	    <p class="sideMenuLabel">frequency</p>
	    <input id = "frequency" type="range" name="volume" min="2" max="30" value="{{freqVal}}" ng-model="freqVal">
	    <p id="sliderValue">{{freqVal}} min</p>
	  </div>
	  <div class="item item-button-right" ng-click="setSettings(newDurVal,newFreqVal)">
    	<p>
        <a class="button icon icon-right ion-chevron-right" href="#/app/photographing">Next</a>
      </p>
  	</div>
	</div>
  </ion-content>
</ion-view>

the controller:

.controller('SetupCtrl', function($scope, $stateParams, $localstorage) {
    $scope.setSettings = function(newDurVal, newFreqVal){
    $localstorage.set('durVal',newDurVal);
    $localstorage.set('durFreq',newFreqVal);
    console.log('newDurVal ' + newDurVal);
    console.log('newFreqVal ' + newFreqVal);
    console.log('durVal ' + $localstorage.get('durVal','durVal undefined'));
    console.log('freqVal '+ $localstorage.get('freqVal','freqVal undefined'));
  }
});

the factory

angular.module('myFactory', [])

.factory('$localstorage', ['$window', function($window) {
  return {
    set: function(key, value) {
      $window.localStorage[key] = value;
    },
    get: function(key, defaultValue) {
      return $window.localStorage[key] || defaultValue;
    },
    setObject: function(key, value) {
      $window.localStorage[key] = JSON.stringify(value);
    },
    getObject: function(key) {
      return JSON.parse($window.localStorage[key] || '{}');
    }
  }
}]);

I don’t know why, but when I click the ‘next’ button to go to the next view, none of the data seems to be persisting.

My logs are:

newDurVal undefined
newFreqVal undefined
durVal undefined
freqVal undefined

Help please?

repo: http://github.com/flomerboy/hourglassPrototype


#12

Your GitHub is plagued with errors that I can’t quite figure out.

What happens when you use window instead of $window in your factory? And are you sure you’re passing a defined value into the $localStorage.set to begin with?

Regards,


#13

Didn’t realize it was plagued with errors! I thought that the data persisting problem was the only one :sweat:

I tried using window instead of $window, it didn’t fix it.

I think that the problem is that I’m not sending $localStorage.set a defined value. But the problem is that I don’t know how or where that defining should happen because I’m a noob.

I think the problem is in here:

.controller('SetupCtrl', function($scope, $stateParams, $localstorage) {
    $scope.setSettings = function(newDurVal, newFreqVal){
      $localstorage.set('durVal',newDurVal);
      $localstorage.set('durFreq',newFreqVal);
      console.log('newDurVal ' + newDurVal);
      console.log('newFreqVal ' + newFreqVal);
      console.log('durVal ' + $localstorage.get('durVal','durVal undefined'));
      console.log('freqVal '+ $localstorage.get('freqVal','freqVal undefined'));
  }
});

or here

<div class="item item-button-right" ng-click="setSettings(newDurVal,newFreqVal)">
    	<p>
        <a class="button icon icon-right ion-chevron-right" href="#/app/photographing">Next</a>
      </p>
  	</div>

those newDurVal and newFreqVal variables were defined in an ngInit in a parent div

Thanks!


#14

It works now! I think I needed to just work a lot more slowly and test 1 thing at a time.

still this repo: https://github.com/flomerboy/hourglassPrototype


#15

BTW, why we need to add a $ prefix to it? If add $ as prefix, it means it is the library form ionic but not user created. Anyone could help?