AngularJS: What is the best way to bind a directive value to a service value changed via a controller?

StackOverflow https://stackoverflow.com//questions/22027820

Question

I want to create a "Header" service to handle the title, buttons, and color of it.
The main idea is to be able to customize this header with a single line in my controllers like this:

function HomeCtrl($scope, Header) {
    Header.config('Header title', 'red', {'left': 'backBtn', 'right': 'menuBtn'});
}

So I created a service (for now I'm only focussing on the title):

app.service('Header', function() {
    this.config = function(title, color, buttons) {
        this.title = title;
    }
});

...And a directive:

app.directive('header', ['Header', function(Header) {
    return {
        restrict: 'E',
        replace: true,
        template: '<div class="header">{{title}}</div>',
        controller: function($scope, $element, $attrs) {
            $scope.$watch(function() { return Header.title }, function() {
                $scope.title = Header.title;
            });
        }
    };
}]);

So, this actually works but I'm wondering if there are no better way to do it. Especially the $watch on the Header.title property. Doesn't seem really clean to me.

Any idea on how to optimize this ?

Edit: My header is not in my view. So I can't directly change the $scope value from my controller.

Edit2: Here is some of my markup

<div class="app-container">
    <header></header>

    <div class="content" ng-view></div>

    <footer></footer>
</div>

(Not sure this piece of html will help but I don't know which part would actually...)

Thanks.

Était-ce utile?

La solution

Simple solution may be to just add to rootScope. I always do this with a few truly global variables that every controller will need, mainly user login data etc.

app.run(function($rootScope){
    $rootScope.appData={
            "header" :  {"title" : "foo"}, 
            "user" :{}
    };
});

.. then inject $rootScope into your controllers as warranted.

Autres conseils

If you are using title in your view, why use scope to hold the object, rather than the service? This way you would not need a directive to update scope.header, as the binding would update it if this object changes

   function HomeCtrl($scope, Header) {
     $scope.header = Header.config('Header title', 'red', {'left': 'backBtn', 'right': 'menuBtn'});
    }

and refer to title as

<h1>{{header.title}}</h1>

Update

Put this in a controller that encapsulates the tags to bind to the header:

$scope.$on("$routeChangeSuccess", function($currentRoute, $previousRoute) {
    //assume you can set this based on your $routeParams
    $scope.header = Header.config($routeParams);
});
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top