Cathal
Cathal

Reputation: 1790

updating data between controller, service and directive

I've written a pretty simple test app as follows:

angular.module('tddApp', [])

.controller('MainCtrl', function ($scope, $rootScope, BetslipService) {
    $scope.displayEvents = [
        {
            id: 1,
            name: 'Belarus v Ukraine',
            homeTeam: 'Belarus',
            awayTeam: 'Ukraine',
            markets: {home: '2/1', draw: '3/2', away: '5/3'},
            display: true
        }
    ];
    $scope.betslipArray = BetslipService.betslipArray;
    $scope.oddsBtnCallback = BetslipService.addToBetslip;
    $scope.clearBetslip = BetslipService.clearBetslip;
})

.directive('oddsButton', function () {
    return {
        template: '<div class="odds-btn">{{market}}</div>',
        replace: true,
        scope: {
            market: '@',
            marketName: '@',
            eventName: '@',
            callback: '&'
        },
        link: function (scope, element) {

            element.on('click', function() {
                scope.callback({
                    name: scope.eventName,
                    marketName: scope.marketName,
                    odds:scope.market
                });
            });
        }
    };
})

.factory ('BetslipService', function ($rootScope) {
    var rtnObject = {};

    rtnObject.betslipArray = [];

    rtnObject.addToBetslip = function (name, marketName, odds) {
        rtnObject.betslipArray.push({
            eventName: name,
            marketName: marketName,
            odds: odds
        });
    };

    rtnObject.clearBetslip = function () {
        rtnObject.betslipArray = [];
    };

    return rtnObject;
});

I've assigned an array to a controller variable. I've also assigned functions to modify the array. To add an object to the array the callback is called by a directive with isolate scope. There's some strange behaviour happening that I don't quite understand:

=> clicking the directive runs the callback in the service. I've done some debugging and it seems that the controller variable is updated but it doesn't show in the html. => clicking the button to clear the array isn't working as expected. The first time it's causing an element to display, after which it has no effect.

I think that this may have to do with the nested ng-repeats creating their own scopes

NB

I fixed the array not clearing by changing the function in the service to:

while (rtnObject.betslipArray.length > 0) {
    rtnObject.betslipArray.pop();
}
// instead of 
rtnObject.betslipArray = [];

This makes sense as the service variable was being pointed at a new object while the old reference would persist in the controller.

I got the html to update by wrapping the callback call in the directive in a scope.$apply(). This part I dont really understand. How can scope.$apply() called in the directive have an effect on the controller scope when the directive has an isolate scope? updated fiddle: http://jsfiddle.net/b6ww0rx8/7/

Any thought's greatly appreciated

jsfiddle: http://jsfiddle.net/b6ww0rx8/5/

C

Upvotes: 0

Views: 288

Answers (1)

m.e.conroy
m.e.conroy

Reputation: 3538

I got it working here: http://jsfiddle.net/b6ww0rx8/8/

Added $q, $scope.$emit and $timeout clauses to help with communications between your directive / service and controller.

I would like to also say that I wouldn't assign service functions to a controller $scope, You should define functions in the controller that call service functions.

Instead of this:

$scope.clearBetslip = BetslipService.clearBetslip;

Do this:

$scope.clearBetslip = function(){
    BetslipService.clearBetslip().then(function(){
        $scope.betslipArray = BetslipService.getBetslipArray();
    });
};

Upvotes: 1

Related Questions