mtpultz
mtpultz

Reputation: 18298

AngularJS how to setup two way data binding between a service and a controller

How would you on connect two way data binding between a service and controller? I've looked at a couple posts, such as How to make two-way data binding between service and controller, but I don't understand the answer. Can someone provide a simple, high-level explanation or example? I've looked into using $watch, but I've also noticed a lot of people saying it shouldn't be used in controllers ie. Angular JS - you probably shouldn't use $watch in your controllers, which just adds to the confusion since I don't know where else I would add it.

Included dependencies from main app.js

(function() {
    'use strict';

    angular.module('myApp', [
        'ngRoute',
        'app.controller',
        'app.service',
        'component.navbar'
    ]);
})();

Included dependencies from navbar component

(function() {
    'use strict';

    /* Navbar Component */

    angular.module('component.navbar', [
        'component.navbar.controller',
        'component.navbar.directive',
        'component.navbar.service'
    ])

    .run(function( NavbarService ) {
        NavbarService.getJSON();
    });

})();

Navbar component snippets

(function() {
   'use strict';

   angular.module('component.navbar.service', [])

   .factory('NavbarService', ['$http', function( $http ) {

       var navbarJSON = [];
       var active = 0;


        var getJSON = function() {

            return $http.get('app/data/navlinks.json')
                .success( function( data ) {
                    navbarJSON = data;
                });
        }

        var getData = function(  ) {

            return navbarJSON;
        }

        var setActive = function( index ) {
            active = index;
        }

        var getActive = function() {
            return active;
        }

        return {
            getJSON: getJSON,
            getData: getData,
            setActive: setActive,
            getActive: getActive
        }

    }]);

})();

(function() {
    'use strict';

    angular.module('component.navbar.controller', [])

    .controller('NavbarController', ['$scope', 'NavbarService', function( $scope, NavbarService ) {

        $scope.navbarData = NavbarService.getJSON();

        $scope.active = NavbarService.getActive();

        $scope.setActive = function( index ) {
            //$scope.active = $scope.navbarData[index]
            NavbarService.setActive( index );
        }

    }]);

})();

Upvotes: 1

Views: 950

Answers (3)

ryeballar
ryeballar

Reputation: 30118

You could have just chosen to pass the service as a $scope property and then use its methods as it is:

Javascript

Controller

.controller('NavbarController', ['$scope', 'NavbarService', function( $scope, NavbarService ) {

    NavbarService.getJSON();
    $scope.navbar = NavbarService;

}]);

HTML (Example)

<nav ng-controller="NavbarController">
  <a ng-repeat="link in navbar.getData()"
     ng-class="{'active': navbar.getActive() == $index}"
     ng-click="navbar.setActive($index)">
     {{link.label}}
  </a>
</nav>

Upvotes: 1

Oliver Salzburg
Oliver Salzburg

Reputation: 22099

Why not just expose active in your service? If you need getter/setter, use implicit ones.

Regarding the suggestion not to use $watch in controllers. That is a pretty generic statement. If $watch is the right tool, use it. If you can achieve the same with an event listener, do that.

In your case your service could broadcast an event on the root scope to signal a change of state. You could listen for that event in your controller and update your value instead of using $watch.

Upvotes: 0

Toan Nguyen
Toan Nguyen

Reputation: 11601

You need to import your service module to your controller module first

angular.module('component.navbar.controller', ['component.navbar.service'])

and I can't see where you have called NavBarService.getJSON (), so called it first to get the data.

Upvotes: 0

Related Questions