AngularJS factory with local storage functionality

As a newcomer to IonicFrameWork, I decided to try out their "starter tab" template and made some tweaks to the functionality of deleting and bookmarking items from a factory.

In my books.js file where the factory is defined, here's a snippet of what it looks like:

.factory('Books', function() {

  // books data
  var books = [{
    id: 0,
    title: 'Sample Title',
    author: 'Sample Author',
    category: 'Horror, Fiction',
    cover: '/cover.jpeg',
    details: 'some details about the book',
    chapters: [
      {
        id : 1,
        name: 'Chapter 1',
        filename: 'chapter1.html',
      },
      {
        id : 2,
        name: 'Chapter 2',
        filename: 'Chapter2.html',
      }
    ]
  }
  .....  
  return {
    all: function() {
      return books;
    },
    // remove a book from the list
    remove: function(book) {
      books.splice(books.indexOf(book), 1);
    },

Then, in my controllers.js, I have the following setup:

....
.controller('DashCtrl', function($scope, Books) {

  $scope.books = Books.all();
  $scope.remove = function(book) {
    Books.remove(book);
  };
})
.controller('singlebookCtrl', function($scope, $stateParams, Books){
  $scope.book = Books.get($stateParams.bookId);
  $scope.toggleIcon = function ($event, iconName, book){
  var buttonClasses = $event.currentTarget.className;
  // add the book to favorite
  if (....){
      book.isFavorite = true;
  }
  // remove the book from favorite 
  else {
      book.isFavorite = false;
  }
  ....

Here's the issue I encountered - when I close the app and open it again, the deleted item reappears and the favorited items are no longer saved.

After researching for a solution, I stumbled upon this informative article suggesting the use of window.localstorage for data persistence. However, I'm unsure how to implement this method within a factory structure.

Answer №1

In my opinion, I find ngStorage to be the most convenient option when it comes to utilizing

localStorage & sessionStorage
.

For instance, once you have added the dependency in your controller, you can easily:

Assign a value :

$scope.favoriteNumbers = [1, 4, ...]
$scope.dataList = { ... }
$localStorage.favorites = $scope.favoriteNumbers;
$localStorage.dataList = $scope.dataList;

Retrieve a value, Simply retrieve the localStorage data :

var favoriteNumbers = $localStorage.favorites;

Answer №2

When working with Local Storage, you can think of it as a key/value store similar to a JavaScript object. To save a value in local storage, simply use the following code snippet.

window.localStorage["bookOne"] = "VALUE GOES HERE"

If you need to store a JavaScript object:

window.localStorage["bookOne"] = JSON.stringify({key: value})

Your data should remain intact even after reloading the page.

Answer №3

The main concern lies in the code you have written, where the variable books is set on each load using var books = .... This means that every time the application is reloaded, the books data is refreshed and any favorites selections will be lost. To address this issue, in addition to saving data to window.localStorage, you will also need to retrieve the saved data from local storage and assign it to both the books and favorites variables when your application loads. Only then will you be able to retain the changes previously made.

Answer №4

If you're looking to tackle this issue, utilizing the angular-local-storage module is your best bet. Below is an example tailored to address your specific challenge:

angular.module('app', ['LocalStorageModule'])
  .factory('Books', function(localStorageService) {
    // List of favorite books (by ID)
    var favList = [1, 2, 3, ...];
    // ....
    return {
      remove: function(id) {
        favList.splice(favList.indexOf(id), 1);
        // Update localStorage
        localStorageService.set(favorites, favList);
      },
      // ....
    }
  });

Keep in mind, you have the option to leverage angular-local-storage#bind and connect a specific scope-key to this service for automatic synchronization. Here's an example:

// Within your controller
$scope.favList = [1, 4, ...]
// Receives a deregistration function for this listener.
$scope.unbind = localStorageService.bind($scope, 'favList');

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Customizing the CSS shadow for a specific ionic select text color, while ensuring that other ion select instances remain unaffected

I'm encountering an issue while attempting to customize the text color inside an ion select element based on the option selected. Unfortunately, when I make changes to the shadow part in one component, it affects other components as well. I want to ap ...

Oops! A JSON parsing error occurred due to the presence of an unexpected token '}'

I encountered an issue while trying to develop a registration route using passportjs. When sending a request via Postman, I received the following error message: SyntaxError: Unexpected token } in JSON at position 119    at JS ...

Exclusive Modal Pop-Up for First-Time Visitors - Utilizing Bootstrap, PHP, and JavaScript

Seeking assistance from the community as I have exhausted my online research efforts. I am currently working on implementing a welcome bootstrap modal in a php environment. Despite being new to php and js, I have managed to make it pop up only once using ...

The data from the Flickr API is consistently unchanging

I created a simple weather app that retrieves weather data using a "POST" request and displays it successfully. Users have the ability to search for weather by city, and I wanted to enhance the app by loading an image of that city through a separate jQuer ...

What is the best way to secure videos and other static files with authentication in a next.js web application?

My goal is to provide static content, specifically videos, exclusively to authorized visitors. I want to secure routes so that they are only accessible to authenticated users. However, the challenge arises when trying to display a video on a page located i ...

What is the best way to handle sequential $http calls in AngularJS? Specifically, I want to make the second $http call dependent on the response of the first

When making two $http calls, the second call should only be executed based on the response from the first call if there is an error present. ...

Is it possible to use both "npm install --global" and "--save" simultaneously?

I'm curious if it is practical to use both the --global and --save parameters in the npm install command simultaneously. For instance: npm install gulp -g -s From my understanding, since there is no package.json in the npm system folder, I assume th ...

Setting a cookie within an Angular interceptor

My angular interceptor function includes a request object. intercept(req: HttpRequest<any>, next: HttpHandler) { return next.handle(req); } I am looking to set my token in the request cookie under the name my-token. How can I achieve this? I ...

Tips for creating a fixed footer that adjusts with a flexible wrapper

Feeling incredibly stressed, I embarked on a quest to find the perfect sticky footer. After searching Google for what seemed like an eternity, I came across multiple tutorials recommending the use of min-height:100%. However, this approach caused the wrap ...

Creating a CSS grid layout with a scrollbar positioned on the left side and content filling from left to right

How can I move the scrollbar to the left while keeping ng-repeat population from left to right? I'm using an ng-repeat to fill a grid that is 3 by X (Width by height). By default, the scroll bar appears on the right side. I want to position it on the ...

Verify whether the marker falls within the circumference of the circle using AngularJS

I am currently working on determining whether a specific marker falls within the radius of a circle. Additionally, I want to trigger an alert displaying the position of the marker when it is clicked. This functionality is being implemented using ng-map. V ...

Determining the page's coordinates in ColdFusion

Whenever I use iframes or frames on older websites, I implement an additional security measure using a JavaScript function: <SCRIPT LANGUAGE="JavaScript1.1"> if (top == self) self.location.href = "../index.cfm"; </SCRIPT> I also include an ...

Is there a way to streamline the form completion process on my website by utilizing voice commands through the user's microphone?

My webpage features a web form using Flask where users manually input their information that is then added to a table upon submitting. The current setup involves an autoplay video prompting users with questions, which they answer manually and then submit t ...

Is there a way to seamlessly integrate typeahead.js with jquery.validate?

Currently, I have a website built on ASP.NET MVC 5 which utilizes jQuery validation (specifically 'jquery.validate.js' in the MVC project template). My goal is to implement type-ahead functionality using 'typeahead.js' on an input field ...

Using Javascript, load a URL by making a JQuery ajax GET request and specifying custom headers

I currently have a small single-page application (SPA) using JQuery/Ajax for the frontend and Node/Express for the backend. The user authentication and authorization are handled with JSON-Webtoken, but I encountered an issue. If someone tries to access the ...

Break down and extract elements using typedEvent in TypeScript

Within the external library, there is the following structure: export interface Event extends Log { args?: Result; } export interface TypedEvent<EventArgs extends Result> extends Event { args: EventArgs; } export type InstallationPreparedEven ...

The base64 code generated by the toDataURL method on the canvas appears to be incorrect

I am facing an issue with my code while using canvas to draw a cropped image with base 64. The problem is that it works perfectly on Chrome but gives me a blank image on Firefox. async function base64SquareCrop(imgbase64, size = 224) { const img = docume ...

Notification within the conditional statement in React JS

I am working on validating phone number input within a React JS component using an if/else statement. If the user enters letters instead of numbers, I want to display a message saying "please check phone number". While I have been able to create a function ...

Guide on developing a personalized validation system with Vuetify regulations for verifying the presence of an item

I'm currently working on my first CRUD web app using Vue 2 + Vuetify, but I've hit a roadblock while trying to add validation to a form. Specifically, I need to ensure that no item with the same title already exists in the database. You can view ...