Watch $localStorage for changes

2.4k views Asked by At

I am using the ngStorage modules which can be found here: https://github.com/gsklee/ngStorage

I am setting a lastSeenId in localStorage for a live updating social feed, as this is a hybrid app (Laravel/AngularJS) I can't store it in $scope.

My StatusesController gets a array or data (or nothing if none to view) ever X seconds and I get the last item of the array and set my $localStorage var like this: $localStorage.lastStatusSeen = lastId;

My navigation controller is where I set some new counters for the user to see if they have missed anything, I am getting lastSeenId like this: $scope.$storage.lastStatusSeen which gets sent over to my API to return a number of unseen status posts.

This all works, user is on status page, if new data, then set the local storage var to the last ID in the array of data.

The issue is that my NavigationController is not finding this change and always passes the lastSeenId that was passed when the user first visited the page.

Is there a way to watch that key in local storage for changes?

EDIT: As requested, updated code

    app.controllers.navigationController = ['$scope', 'pollingService', '$localStorage', function($scope, pollingService, $localStorage) {

    $scope.lastStatusSeen = $localStorage.lastStatusSeen;

    $scope.$watch(function () {
        return $localStorage.lastStatusSeen;
    }, function (newVal, oldVal) {
        if (!newVal) {
            return;
        }

        if (newVal !== oldVal) {
            // Assign to a local scoped var, or anything, here...
            $scope.lastStatusSeen = newVal;
            // I suggest call a method to do your logic outside this
            //$scope.onIdChange(newVal, oldVal); // If you need oldVal
        }
    });

    pollingService.startPolling('emailCount', 'api/email/new-count', 5000, function(response) {
        $scope.emailCount = response.data;
    });

    pollingService.startPolling('statusCount', 'api/social/new-count?lastid=' + $scope.lastStatusSeen, 5000, function(response) {
        $scope.socialCount = response.data;
    });

}];
1

There are 1 answers

6
Mateus AJ Leon On BEST ANSWER

You can watch it using the $watch method of any scope entity of angular ($scope or $rootScope):

$scope.$watch(function () {
    return $localStorage.lastStatusSeen;
}, function (newVal, oldVal) {
    if (!newVal) {
       return;
    }

    if (newVal !== oldVal) {
        // Assign to a local scoped var, or anything, here...
        // I suggest call a method to do your logic outside this

        $scope.onIdChange(newVal, oldVal); // If you need oldVal
    }
});

Be careful with performance because this runs almost every $digest cycle. Another note is that you can associate this watcher to a variable, so you can cancel it anytime you need:

var watchIdStored = $scope.$watch(function () {
    /* ... */

When you want to remove it, call the var as a function:

watchIdStored(); // Removes the $watcher

Edit 1:

The problem there is on pollingService.startPolling('statusCount', 'api/social/new-count?lastid=' + $scope.lastStatusSeen. It builds up a string that isn't changed anymore. You have to inform this change as it happens, providing to the poll the update.

If you put a console inside the watcher, where you update the var, you'll see that it's updating.

Edit 2:

As you have a stopPolling() method, you can create a build/destroy function on your controller.

function _setupPolling (name, url, pollingTime, callback) {
    pollingService.stopPolling(name);

    pollingService.startPolling.apply(pollingService, arguments);
}

Now, you call it on every change that occurs on $localStorage.lastStatusSeen:

$scope.$watch(function () {
    return $localStorage.lastStatusSeen;
}, function (newVal, oldVal) {
    if (!newVal) {
        return;
    }

    if (newVal !== oldVal) {
        console.log(newVal);

        // Assign to a local scoped var, or anything, here...
        $scope.lastStatusSeen = newVal;
        // I suggest call a method to do your logic outside this

        _setupPolling('statusCount', 'api/social/new-count?lastid=' + $scope.lastStatusSeen, 5000, function(response) {
            $scope.socialCount = response.data;
        });
    }
});