reZach
reZach

Reputation: 9429

Refresh $scope variables from a service

What is the proper method of refreshing data that is retrieved from a service? I am retrieving a test array from my dataService that I'd like to be automatically updated in my view when my save() method is called. I have commented the line that is supposed to update my $scope variable but yet nothing changes. Should I be wrapping it in $apply()?

The data that is placed into the array that dataService.getActivities() returns is from a cookie (which may or not be relevant).

app.controller("activityCtrl", ["$scope", "dataService", function ($scope, dataService) {

    $scope.newActivity = "";
    $scope.activities = dataService.getActivities();

    $scope.save = function (activity) {

        try{
            if (activity != "") {
                dataService.saveActivity(activity);

                $scope.newActivity = "";
                $scope.activities = dataService.getActivities(); //HERE
            }
        } catch (e) {
            alert(e);
        }        
    }
}

Here is my view, the array lives in a ng-repeat

<div class="col-xs-12" ng-controller="activityCtrl">
    <div class="row text-center">
        <form novalidate>
            <input type="text" placeholder="Activity name" ng-model="newActivity" />
            <input type="submit" value="Add activity" ng-click="save(newActivity)" />
        </form>            
    </div>
    <div class="row" ng-controller="activityCtrl">
        <div class="col-xs-2">&nbsp;</div>
        <div class="col-xs-6 text-left">
            <div class="row" ng-repeat="activity in activities">
                <div class="btn btn-default" ng-class="{ active : activity.active }" ng-click="activate(activity)">{{ activity.name }}</div>
            </div>
        </div>
        <div class="col-xs-4 text-left">
            sdfas
        </div>
    </div>
</div>

dataService code:

app.service("dataService", function () {

this.getActivities = function () {

    if (docCookies.hasItem("activities")) {

        var activities = JSON.parse(docCookies.getItem("activities"));

        if (activities.constructor != Array) {

            activities = [activities];
        }

        activities.sort(
            function (a, b) {
                if (a.name > b.name) { return 1; }
                if (b.name < a.name) { return -1; }
                return 0;
            });

        return activities;
    }

    return [];
}

this.saveActivity = function (activity) {

    if (!docCookies.hasItem("activities")) {

        docCookies.setItem("activities", [JSON.stringify({ "name": activity, "active": true })], Infinity);
    } else {

        var activities = this.getActivities();

        for (var i = 0; i < activities.length; i++) {

            if (activities[i].name == activity) {
                throw "Activity already exists";
            }
        }

        activities.push({ "name": activity, "active": false });
        docCookies.setItem("activities", JSON.stringify(activities), Infinity);
    }

};
});

Upvotes: 0

Views: 573

Answers (2)

JK Dennis
JK Dennis

Reputation: 661

Zac, your answer should work for you. As another option, I like to broadcast an event whenever my service is updated. In the last line of your saveActivity() function in your service, try broadcasting an event on the rootScope. Inject the $rootScope into your service. Add the following to your save method:

$rootScope.$broadcast('activitiesUpdated');

Then in your controller, inject the $rootScope and add an event handler:

$rootScope.$on('activitiesUpdated', function(event, args){
     //Update $scope variable here
});

Upvotes: 1

reZach
reZach

Reputation: 9429

The answer was to look at the cookie value with a call to $watch instead of the method that returns an object. Added this in my activityCtrl

$scope.$watch(function () {

    return docCookies.getItem("activities");
}, function (oldVal, newVal) {

    $scope.activities = dataService.getActivities();
});

Upvotes: 0

Related Questions