1

To be honest I am a bit new to angularjs, so this may be problem with my fundamental understanding of angular, rather than angular-charts.

I have two controllers (PieItemsCtrl and PieCtrl) and I would like to communicate between them by using a factory service (called pieItems)

On the one hand the pieItems works as designed in the PieItemsCtrl.

ie:

$scope.slices =  pieItems.list();

Whenever something changes in the pieItems service (ie another element is added), then the HTML is automatically updated via a repeater :

<div ng-repeat="(key, val) in slices">

However in the PieCtrl I have this line, and i would expect the pie chart to update automatically :

$scope.labels = pieItems.labelsItems();
$scope.data = pieItems.data();

It seems to set these data values upon loading/initialisation of the PieCtrl and that's it. Whenever the pieItems data changes these scope values are not updated.

The source of the two controller and factory object are below. And I also made an unworkable fiddle, incase that helps

PieItemsCtrl :

app.controller('PieItemsCtrl', function($scope, $http, $rootScope, pieItems) {

        $scope.slices =  pieItems.list();
        $scope.buttonClick = function($event) {
            pieItems.add(
                {
                    Name: $scope.newSliceName,
                    Percent: $scope.newSlicePercent,
                    Color: $scope.newSliceColor
                }
            )
        }

        $scope.deleteClick = function(item, $event) {
            pieItems.delete(item);
        }
    } 
)

PieCtrl :

app.controller("PieCtrl", function ($scope, $timeout, pieItems) {
    $scope.labels = pieItems.labelsItems();
    $scope.data = pieItems.data();
});

pieItems :

app.factory('pieItems', function() {
    var items = [];

    var itemsService = {};

    itemsService.add = function(item) {
        items.push(item);
    };
    itemsService.delete = function(item) {

        for (i = 0; i < items.length; i++) {
            if (items[i].Name === item.Name) {
                items.splice(i, 1);
            }
        }
    };
    itemsService.list = function() {
        return items;
    };

    itemsService.labelsItems = function() {

        var a = ['x', 'y'];
        for (i = 0; i < items.length; i++) {
            a.push(items[i].Name);
        }
        return a;
    };
    itemsService.data = function() {

        var a = [50,50];
        for (i = 0; i < items.length; i++) {
            a.push(items[i].Percent);
        }
        return a;
    };

    return itemsService;
});

1 Answer 1

1

The controller doesn't notice when the value in your factory changes. To include your item-Array in an Angular digest-cycle, tell Angular to $watch that Array.

If you don't want to expose the Array, create a getter:

itemsService.get = function() { return items; }

Then you can include that getter in your $watch expression in your controller:

$scope.$watch(getItems, watcherFunction, true);
function getItems() {
    return pieItems.get();
}

The getItems-Function gets called on digest cycle and fires the watcherFunction if the value changed and has the newData as argument. true as 3rd argument creates a deep watch.

function watcherFunction(newData) {
     console.log(newData);
     // do sth if array was changed
}

For more complex objets, you can use a $watchCollection.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.