Pirozek
Pirozek

Reputation: 1270

Using scope in directive and service

I am trying to create a developer console in my Angular app and I have the following problem.

On every page of my application I want my developer console to be available (like a floating thing in a corner of the screen). I have HTML template and I am switching content with ui-view. My controllers can include consoleService and then call something like myConsole.log(...). This function should add message to some array and then display it on web. For my console I have directive with HTML template, where I want to use ng-repeat to display all messages.

And now my problem. How should I design this? I was thinking like this:

First solution

Well, I can create global JS variable, store all messages there and then use <script> and write em out in my directive template.

WRONG! Not respecting Angular-way of doing things

Second solution

Ok, I`ll use $scope and put my messages there, and then I can use that magical Angular data bind to just let it work on its own. Ok, but here I have a problem, how can I inject $scope into my service?

WRONG! Injecting $scope into service is nonsense, because it would not make any sense, and again, it kinda oppose the Angular-way.

Third solution

Fine, lets store my messages on console service, since all services in Angular are singletons it should work pretty fine, but... there is no $scope inside a service, so I need to return this array of messages to a controller and then assign it to $scope in controller.

??? What do you think? My problem with this solution is that in every controller I need to assign message array to $scope and I just dont want to do that, since I need this console everywhere, on every page.

I hope that my explanation of what I want to do is clear, so I am just hoping for a hint, or advice on how to design it in Angular.

Upvotes: 0

Views: 69

Answers (1)

Joao Leal
Joao Leal

Reputation: 5542

Use the third solution. Your service will have an array with all the messages and each controller can use one of it's functions (service.log(...)) which will basically just add one message to the service list.

Then on your directive, you just assign the getMessages to the directive scope:

var app = angular.module('plunker', []);

app.service('log', function(){
  var messages = [];
  return {
    getMessages: function() { return messages; },
    logMessage: function(msg) { messages.push(msg); }
  }
})

app.controller('MainCtrl', function($scope, log) {
  $scope.msg = '';

  $scope.addMessage = function() {
    log.logMessage($scope.msg);
  };
});

app.directive('console', function(log) {
  return {
    restrict: "E",
    scope: {},
    replace: true,
    template: "<div><div ng-repeat='msg in messages'>{{msg}}</div></div>",
    link: function(scope, el, attr) {
      scope.messages = log.getMessages();
    }
  };
});

plunker: http://plnkr.co/edit/Q2g3jBfrlgGQROsTz4Nn?p=preview

Upvotes: 3

Related Questions