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

Domanda

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.

È stato utile?

Soluzione

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.

Altri suggerimenti

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);
});
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top