AngularJS Informer服务

mad*_*ead 5 jquery dom dom-manipulation angularjs angularjs-service

我在我的webapp中使用Twitter Bootstrap for UI.特别是它的警报组件.我想编写一个简单的角度服务来包装Bootstrap的Alert,以便有可能通知用户任何角度代码的安静.像这样:

Informer.inform("message", "ERROR"); // will result in alerting with `alert-error` class
Informer.inform("message", "INFO"); // will result in alerting with `alert-info` class
Run Code Online (Sandbox Code Playgroud)

我的想法是将模板附加到以下结尾<body>:

<div class="alert {{alertClass}} fade in informer" id="informer">
    <button type="button" class="close" data-dismiss="alert">×</button>
    <div class="valignCenterWrapper">
        <div class="valignCenter" id="informerMessage">
            {{message}}
        </div>
    </div>
</div>
Run Code Online (Sandbox Code Playgroud)

像这样的东西:

grfx.factory("Informer", function() {
    return {
        inform : function(message, type) {
            // Here be dragons. How can I compile/append the template.

            $("#inform").alert();
        }
    };
});
Run Code Online (Sandbox Code Playgroud)

我唯一想知道的是:如何使用angular来编写它,而不是使用jQuery?上面的代码是否适合开始?互联网中的人说我应该使用指令进行DOM操作.但我不明白:我没有任何现有的标记来应用它的指令.由于某些compupations /用户交互,警报将附加到页面.哪些服务($compile,$parse,$document)我应该使用编译temlate和地方追加它的身体吗?

编辑:是否也可以在控制器之外获得angularjs服务.只是在常规的JS代码中,所以我可以写getServiece("Informer").inform("", "")

编辑2:好的,我现在拥有的:

grfx.factory("Informer", function($compile, $rootScope) {
    return {
        inform : function(message, type) {
            var scope = $rootScope.$new();

            scope.message = message;
            scope.type = type;

            $(document.body).append($compile("<div class='alert {{type}} fade in informer' id='informer'><button type='button' class='close' data-dismiss='alert'>×</button><div class='valignCenterWrapper'><div class='valignCenter' id='informerMessage'>{{message}}</div></div></div>")(scope));
        }
    };
});
Run Code Online (Sandbox Code Playgroud)

使用此代码,我可以使用来自控制器的注入服务.但是当我尝试在角度代码之外调用服务时会出现问题:

angular.element(document).injector().get("Informer").inform("Message", "alert-error");
Run Code Online (Sandbox Code Playgroud)

这显示弹出窗口,{{message}}例如它无法正确编译模板.

pko*_*rce 8

在AngularJS中,我们应该专注于模型操作,你的Informer服务也不例外 - 它应该只保存模型而不应该关注DOM操作.DOM操作=指令的经验法则非常好,如果你遵循它,它将为你节省很多麻烦.

回到你手头的问题,解决方案是让服务专注于模型操作和指令来显示这个模型.让我们从服务开始:

app.factory('Informer', function(){

  var messages = [];  
  var Informer = {};

  Informer.inform = function(msg, type) {
    messages.push({
      msg: msg,
      type: type
    });
  };

  Informer.allInfos = function() {
    return messages;
  };

  Informer.remove = function(info) {
    messages.splice(messages.indexOf(info), 1);
  };  

  return Informer;
});
Run Code Online (Sandbox Code Playgroud)

当此服务准备就绪时,您可以轻松地在控制器中使用它(甚至在其他服务中!):

app.controller('MainCtrl', function($scope, Informer) {

  Informer.inform("error message", "error");
  Informer.inform("info message", "info");

  $scope.allInfos = Informer.allInfos;  
  $scope.remove = Informer.remove;
});
Run Code Online (Sandbox Code Playgroud)

最后,为了呈现警报,您可以直接使用bootstrap的标记,或者编写一个封装它的非常简单的指令.在这里,我使用来自http://angular-ui.github.com/bootstrap/的警报指令

<body ng-controller="MainCtrl">
    <alert ng-repeat="alert in allInfos()" type="alert.type" close="remove(alert)">{{alert.msg}}</alert>
  </body>
Run Code Online (Sandbox Code Playgroud)

当然,您不需要使用此repo中的指令,您可以根据需要创建自己的指令或使用原始标记.

这是一个演示一个工作示例的plunker:http://plnkr.co/edit/VxAcjHFhxXODFB5iAfyX?p = preview

总结一下:

  • 根据经验,不要在指令之外进行DOM操作
  • 处理模型的服务应该与模型的表示分离

我还建议在学习 AngularJS时从项目中删除jQuery .这样你就可以更快地进入AngularJS-zen状态!