The contents of the $localStroage array do not align with those of the $scope array

I am storing objects in a `$localStorage` array for persistence. I have a check function to see if an object is already present in the array before adding or removing it (using `splice` if present, and `push` if not).

However, after refreshing my page, the data retrieved from `$localStorage` seems different than before, even though it appears identical upon inspection. Therefore, my check function no longer works properly.

The structure of the objects being pushed:


    {
    "createdAt": "2015-04-24T10:21:21.649Z",
    "difficulty": "Hard",
    "exerciseDescription": "Lie on your back on a bench and take hold",
    "exerciseID": "3101",
    "exerciseName": "Bench Press",
    "images": [8679, 8680, 8682],
    "tags": ["Barbell", "Horizontal Flexion", "Extension", "Strength", "Chest", "Triceps", "Shoulder", "Elbow, Wrist & Hand"],
    "updatedAt": "2015-09-09T20:14:59.681Z",
    "words": ["bench", "press", "chest"],
    "objectID": "ak6t7ukQdY",
    "_highlightResult": {
        "exerciseName": {
            "value": "Bench Press",
            "matchLevel": "none",
            "matchedWords": []
        }
    }
}

Check for object presence (toggle add/remove)

$scope.addExerciseToProgramme = function(exercise) {

    if (!$localStorage.Programme) {
        $localStorage.Programme = [];
    }

    var index = $localStorage.Programme.indexOf(exercise);

    if (index > -1) {
        $localStorage.Programme.splice(index, 1);
    } else {
        $localStorage.Programme.push(exercise);
    }
}

Function to watch/load $localStorage

$scope.$watch(function() {
    return $localStorage.Programme
}, function(programme) {
    $scope.programme = programme;
});

ng-class to check if exercise is in programme

<i class="exercise-add-indicator ion-ios-checkmark-outline" ng-class="{'orange': programme.indexOf(exercise) > -1}"></i>

Issues

There are two issues with the current setup:

  1. After refresh, the `ng-class` does not correctly apply the class based on the content of `$scope.programme`.

  2. The `addExerciseToProgramme` function does not respect the `indexOf` check and adds the exercise object to the array regardless!

Answer №1

When using Array.prototype.indexOf(), keep in mind that it uses strict equality: <em>An evaluation comparing objects returns true only if they reference the same object.</em></p>

<p>Avoid using this method when interacting with localStorage.</p>

<p>Objects stored in localStorage are converted to strings when saved and back to objects when retrieved.</p>

<p>However, upon retrieval, a new object is created, even if it appears identical.</p>

<p>For instance, the following comparison will result in <code>false
:

var obj1 = { id: 1 };
var obj2 = { id: 1 };

console.log(obj1 === obj2);

To address this, you can create a custom function that identifies the index based on a specified property value. This property should be unique.

For instance:

$scope.getIndexByExercise = function(exercise) {

  var idx = -1;

  if (!$scope.program) return idx;

  for (var i = 0; i < $scope.program.length; i++) {

    if ($scope.program[i].exerciseID !== exercise.exerciseID) continue;

    idx = i;
    break;
  }

  return idx;
};

$scope.exercisePresent = function(exercise) {

  var idx = $scope.getIndexByExercise(exercise);
  return idx > -1;
};

$scope.addToProgramme = function(exercise) {

  if (!$localStorage.Programme) {
    $localStorage.Programme = [];
  }

  var idx = $scope.getIndexByExercise(exercise);

  if (idx > -1) $localStorage.Programme.splice(idx, 1);
  else $localStorage.Programme.push(exercise);
};

HTML:

... ng-class="{'orange': exerciseExists(exercise) }" ...

Live Example: http://plnkr.co/edit/N7REitJQ1gkDcwBgw9F3?p=preview

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

Update the variables upon a click event following the completion of an AJAX request

Despite my efforts, I am unable to find a solution to the issue I am currently facing. To address this problem, I have created a script using PHP and jQuery that enables users to promote their "listings" on my website. When users visit a specific page, the ...

Issue with jQuery DataTable: Unable to use column-level filters at the top and maintain a fixed height simultaneously

I am having an issue displaying data in a jQuery DataTable with a column level filter at the top, fixed height, and scroller enabled. Initially, I was able to display the column level filter at the top and it was functioning properly. However, when I set t ...

Fetching information from the server in response to the data transmitted from the client

In need of help with sending a string id from the client to server side and retrieving related information using Node.js for the back-end. I have searched online but haven't found a solution yet. Hoping this isn't a redundant question. ...

Is it possible for a dash in a GET variable name to cause issues with req.query in NodeJS Express?

I am currently developing a GET endpoint in Node.js using Express to handle the following variable: ?message-timestamp=2012-08-19+20%3A38%3A23 However, I am facing difficulty accessing it through req.query. Whenever I try to access req.query.message-time ...

Transforming a string representation of a nested array into an actual nested array with the help of JavaScript

My database stores a nested array as a string, which is then returned as a string when fetched. I am facing the challenge of converting this string back into a nested array. Despite attempting to use JSON.parse for this purpose, I encountered the following ...

``Where can I find information on setting a timeout for a node.js application

Is it feasible to implement a timeout for running node.js? I am faced with the issue of connecting to external services that occasionally do not respond, causing my script to hang and the node.js process to freeze. I am seeking a solution to enforce the t ...

Dealing with rejected responses in AngularJS using UI-Router

I am utilizing a Service in Angular to encapsulate my API requests: var ConcernService = { list: function (items_url) { var defer = $q.defer(); $http({method: 'GET', url: api_url + items_url}) .succe ...

What is the best way to determine the size of a returned element in React?

How can I determine if the description of {book.volumeInfo.description} is empty or not? If the length of {book.volumeInfo.description} is greater than zero, display it; otherwise, show "Book without description". I am unsure of the correct way to get the ...

Utilizing App Script for Filtering Data with Multiple Criteria

Having trouble transferring data from a data sheet to my report sheet using multiple criteria for matching. I wrote some code that worked, but it's returning all data instead of filtering by criteria. I want the function to search for column criteria ...

When running scripts, Protractor is unable to perform a click action in Safari, even though it works perfectly in

Currently, I am in the process of developing an angular application and utilizing directconnect for Chrome and Firefox. All my test scripts are functioning as expected, however, a new requirement has been introduced to run these same tests on Safari. To ...

Angular's implementation of a web socket connection

I am facing an issue with my Angular project where the web socket connection only opens upon page reload, and not when initially accessed. My goal is to have the socket start as soon as a user logs in, and close when they log out. Here is the custom socke ...

yo projectname Angular Command

Every time I run this command, I encounter a new error. It seems like as soon as I fix one module issue, another pops up. For instance, I recently encountered an error with the 'shelljs' module. The specific error message is as follows: Error: ...

Customizing the appearance of a date input field by passing an object with Vue.js

I created a dynamic table using Vuejs, where each cell contains an input element set as readOnly initially. The table also includes an 'edit' button for each row, which, when clicked, changes to 'save' and allows editing of the input el ...

Having trouble getting THREE.Raycaster to intersect with THREE.PointCloud

Currently, I am trying to implement click events on my WebGL based 3D graph library called Graphosaurus. You can take a look at what I have done so far here. I have used this example as a reference. I am wondering if the reason it is not functioning corr ...

Tips for showing all percentages on a Google PieChart

I'm currently encountering two issues. How can I ensure that the entire legend is visible below the graph? Sometimes, when the legend is too large, three dots are added at the end. Another problem I am facing involves pie charts. Is there a way to d ...

Creating a nx workspace for vanilla JavaScript (Error: module 'typescript' not found) - Step-by-step guide

Looking to set up a new workspace for plain React applications. How can I do it? Create Workspace npx create-nx-workspace@latest # version 15.2.1 # style: package-based # distributed caching: NO Installing the react-package npm install -D @nrwl/react Cr ...

When searching for live Ajax in PHP CI, the result is not being displayed on the

I'm puzzled as to why, when I enter names in the input field in this code, no results are displayed. Additionally, I'm getting a Json parser error in my console: SyntaxError: JSON.parse: unexpected character at line 2 column 1 of the JSON data ...

How can I show the total sum of input values in a React.js input box?

Is there a way to dynamically display the sum of values entered in front of my label that updates automatically? For example, you can refer to the image linked below for the desired output Output Image I have initialized the state but I'm struggling ...

Troubleshooting issue with Angular nested ng-repeats and JSON request not functioning properly

I'm trying to create a nested list using ng-repeat and a JSON file: [] Pizza King North Region [] Pizza King 102 [] Pizza King 103 [] Pizza King 104 [] Pizza King South Region [] Pizza King 201 [] ...

Ways to change attributes of deeply embedded objects?

Imagine having a complex object with nested properties like this: const obj = { Visualization: { Lower: [{ name: "Part", selectedValue: "60-000" }], Upper: [{ name: "Part", selectedValue: "60-000" }], ...