4

How to bind a directive to a controller via a service update ?

I want to create the possibility to update a cart(the service) via a directive(add to cart button) and then the controller (that display the cart) will update its view. Despite the fact that I added a watch on the service itself my controller is not been updated.

Of course it will be good if the controller and the directive doesn't share the same scope (transclude: true in the directive)

The service:

    angular.module('stamModule', [])
    .factory('valueService', function () {
    var factory = {
        data: {value: 1000},
        inc: inc,
        getData: getData
    };

    function inc() {
        this.data.value++;
    }

    function getData() {
        return this.data;
    }

    return factory;
})

the directive:

 .directive('buttonDirective', function (valueService) {

    var directive = {
        restrict: 'E',
        template: '<button>Inc</button>',
        link: linkFnc
    };

    function linkFnc(scope, el) {
        el.on('click', function () {
            valueService.inc();
        });
    }

    return directive;
})

The controller:

.controller('FirstController', function ($scope, valueService) {
    var vm = this;
    vm.serv = valueService;

    $scope.$watch('vm.serv.getData()', function (newValue) {
        console.log("watch");
        console.log(newValue);
    });
})

The html:

<body ng-app="stamModule">
<hr>
<div ng-controller="FirstController as vm">
    <p>{{vm.serv.data}}</p>
    <button-directive ></button-directive>
</div>

here's a demo: https://jsfiddle.net/07tp4d03/1/

Thanks

1 Answer 1

2

All your code needed was a little push. No need for event broadcasting or anything like that.

The problem was, that the click event listener was working outside Angular's digest loop, and thus Angular watch wasn't working for you. If you change your directive's code to the following, it will work.

.directive('buttonDirective', function (valueService) {

    var directive = {
        restrict: 'E',
        template: '<button ng-click="inc()">Inc</button>',
        link: linkFnc
    };

    function linkFnc(scope) {
        scope.inc = function() {
            valueService.inc();
        };
    }

    return directive;
})

Here is a fork of your fiddle that works

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

1 Comment

great ! we also doesn't need the $watch in the controller because I bind the service object and then angular pass its reference. I updated the fiddle: jsfiddle.net/xnk0h91w/1 @MaximShoustin: it is a better solution because we don't need to use any broadcast event and then the solution is cleaner. Thank you both !

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.