javascript - AngularJS: How to add and compile a directive to the dom, from a service - Stack Overflow

I think what I am trying to do is fairly simple, but I can't seem to determine the correct archite

I think what I am trying to do is fairly simple, but I can't seem to determine the correct architecture using Angular.

I'd like to have a MessageCenter, so that any controller or other piece of Angular code can add a message. I thought that the correct way to do this would be with a MessageCenter service. I would inject the service where needed, and call MessageCenter.add(). The problem that I am having is how to pile the cloned DOM directive, since $pile requires a $scope, which I do not have from a service.

Here is what I am trying. I am not sure what the correct approach is for this.

<div>
  <div id="msg-proto" message-center-msg class="alert alert-success"></div>
</div>

Then:

.factory('MessageCenter', function($pile) {
  var that = {}

  that.add = function(type, message) {
    var n = $("#msg-proto"),
        n2 =  n.clone();
    n.parent().append($pile(n2));
  }

  return that;
});

And I am injecting and calling the service:

.controller('SomeCtrl', function(MessageCenter) {
  MessageCenter.add('some msg');
});

I have a message-center-msg directive defined that adds some behaviors to the element. But it needs to be $pile'd in order for that to happen, and I am not sure how to make this all work. I only ever end up with "Error: Argument 'scope' is required" from the service.

How can I setup a global message center, that is able to clone/add messages and have the directive on the message dom element processed?

I think what I am trying to do is fairly simple, but I can't seem to determine the correct architecture using Angular.

I'd like to have a MessageCenter, so that any controller or other piece of Angular code can add a message. I thought that the correct way to do this would be with a MessageCenter service. I would inject the service where needed, and call MessageCenter.add(). The problem that I am having is how to pile the cloned DOM directive, since $pile requires a $scope, which I do not have from a service.

Here is what I am trying. I am not sure what the correct approach is for this.

<div>
  <div id="msg-proto" message-center-msg class="alert alert-success"></div>
</div>

Then:

.factory('MessageCenter', function($pile) {
  var that = {}

  that.add = function(type, message) {
    var n = $("#msg-proto"),
        n2 =  n.clone();
    n.parent().append($pile(n2));
  }

  return that;
});

And I am injecting and calling the service:

.controller('SomeCtrl', function(MessageCenter) {
  MessageCenter.add('some msg');
});

I have a message-center-msg directive defined that adds some behaviors to the element. But it needs to be $pile'd in order for that to happen, and I am not sure how to make this all work. I only ever end up with "Error: Argument 'scope' is required" from the service.

How can I setup a global message center, that is able to clone/add messages and have the directive on the message dom element processed?

Share Improve this question asked Sep 29, 2013 at 6:03 vcardillovcardillo 1,7063 gold badges24 silver badges30 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 3

Your service shouldn't interact with the DOM directly as you're trying to do. If I were designing such a system I would:

  1. Have a service which simply takes in messages and either puts them in an array (if you want to support a whole list of messages) or simply remembers the last message (if you only want to support a single message)
  2. Have a controller which gets the message service injected to it and binds the message(s) from the service into its scope
  3. Then have a bit of HTML (or a custom directive) that iterates the messages using the above controller and displays them

Here's what I mean (plunk here: http://plnkr.co/Eps1Gy)

index.html:

<!doctype html>
<html>
  <head>
    <script src="bower_ponents/angular/angular.js"></script>
    <script src="scripts/app.js"></script>  
    <script src="scripts/controllers/messages.js"></script>
    <script src="scripts/controllers/click.js"></script>
    <script src="scripts/services/messageService.js"></script>
</head>
  <body ng-app="messagesApp">
    <h1>Messages</h1>
    <div ng-controller="MessagesCtrl"> 
      <ul  ng-repeat="message in messages">
        <li>{{message}}</li>
      </ul>
    </div>
    <a ng-href="#" ng-controller="ClickCtrl" ng-click="addMessage()" >Add a new message!</a>
  </body>
</html>

messageService.js:

function MessageService() {
    this.messages = [];
    this.add = function(msg) {
        this.messages.push(msg);
    }
}

angular.module('messagesApp')
    .service('messageService', MessageService);

messages.js:

angular.module('messagesApp')
  .controller('MessagesCtrl', function ($scope, messageService) {
    $scope.messages = messageService.messages;
  });

click.js:

angular.module('messagesApp')
  .controller('ClickCtrl', function ($scope, messageService) {
    var count = 0;

    $scope.addMessage = function() {
        messageService.add('Test message ' + count++);
    }
  });

app.js:

angular.module('messagesApp', [])
  .config(function ($routeProvider) {
    $routeProvider
      .otherwise({
        redirectTo: '/'
      });
  });

Like I said, you can replace the HTML for handling the messages with a custom directive if you want some plex interaction, but the important thing is that you don't try to muck with the view from your service. The service should interact only with a well-defined model.

I implemented something pretty identical a while back and recently made this public as a bower ponent. Maybe you can use or work off of it: https://github./IanShoe/angular-message-center

Happy coding!

You can open your mind :)

On your call to the MessageCenter move the $scope as parameter like MessageCenter.add("", $scope);

Or ... you can expose the MessageCenter to the scope globally on startup something like this guy suggested

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745371777a4624825.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信