AngularJS 线人服务 [英] AngularJS Informer service

查看:22
本文介绍了AngularJS 线人服务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在我的 web 应用程序中使用 Twitter Bootstrap 作为 UI.特别是它的 Alert 组件.我想编写一个简单的 angular 服务来包装 Bootstrap 的 Alert,以便有可能通知用户有关 angular 代码的任何和平.像这样:

Informer.inform("message", "ERROR");//将导致带有 `alert-error` 类的警报Informer.inform("消息", "信息");//将导致带有 `alert-info` 类的警报

我的想法是将模板附加到的末尾:

像这样:

grfx.factory("Informer", function() {返回 {通知:功能(消息,类型){//这里是龙.如何编译/附加模板.$("#inform").alert();}};});

我唯一想知道的是:我如何用 angular 而不是 jQuery 来写这个?上面的代码适合开始吗?互联网上的人们说我应该使用 DOM 操作指令.但我不明白:我没有任何现有的标记来应用指令.由于某些计算/用户交互,警报将附加到页面.我应该使用哪些服务($compile$parse$document)来编译模板并将其附加到正文的某个位置?

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

EDIT 2:好的,我现在拥有:

grfx.factory("Informer", function($compile, $rootScope) {返回 {通知:功能(消息,类型){var scope = $rootScope.$new();scope.message = 消息;scope.type = 类型;$(document.body).append($compile("<div class='alert {{type}} 淡入informer' id='informer'><button type='button' class='close' data-dismiss='alert'>×</button><div class='valignCenterWrapper'><div class='valignCenter' id='informerMessage'>{{message}}</div><;/div>

")(范围));}};});

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

angular.element(document).injector().get("Informer").inform("Message", "alert-error");

这会显示带有 {{message}} 的弹出窗口,例如它没有正确编译模板.

解决方案

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

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

app.factory('Informer', function(){var 消息 = [];var 告密者 = {};Informer.inform = 函数(味精,类型){消息.推送({味精:味精,类型:类型});};Informer.allInfos = function() {回消息;};Informer.remove = 函数(信息){消息.拼接(消息.索引(信息),1);};返回线人;});

当这个服务准备好后,你可以很容易地在控制器中使用它(甚至在其他服务中!):

app.controller('MainCtrl', function($scope, Informer) {Informer.inform("错误信息", "错误");Informer.inform("信息消息", "信息");$scope.allInfos = Informer.allInfos;$scope.remove = Informer.remove;});

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

<alert ng-repeat="alert in allInfos()" type="alert.type" close="remove(alert)">{{alert.msg}}</alert>

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

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

总结:

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

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

I'm using Twitter Bootstrap for UI in my webapp. Particulary its Alert component. I want to write a simple angular service to wrap Bootstrap's Alert to have a possibility of informing users from any peace of angular code. Like this:

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

My idea is to to append the template to the end of the <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>

Something like this:

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

            $("#inform").alert();
        }
    };
});

The only thing I want to know: how do I write this with angular, not with jQuery? Is the code above good for start? Folks in the internets say that I should only use directives for DOM manipulation. But I do not understand it: I do not have any existing markup to apply directive on it. Alerts will be appended to the page as a result of some compupations/user interactions. Which services ($compile, $parse, $document) should I use to compile temlate and append it somewhere to the body?

EDIT: Is it also possible to get angularjs service outside of controller. Just in regular JS code so I can write getServiece("Informer").inform("", "")?

EDIT 2: Ok, what I have now:

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));
        }
    };
});

With this code I am able to use injected service from controllers. But there is an issue when I try to call service outside angular code:

angular.element(document).injector().get("Informer").inform("Message", "alert-error");

This shows popup with {{message}} e.g. it does not compile template correctly.

解决方案

In AngularJS we should be focusing on model manipulation and your Informer service is no exception - it should only hold model and shouldn't be concerned with DOM manipulation. The rule of thumb where DOM manipulation = directive is a very good one and if you follow it it will save you a lot of headaches.

Back to your problem at hand, the solution is to have a service focused on model manipulation and a directive to display this model. Let's start with the service:

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;
});

When this service is ready you can easily use it in a controller (or even inside other services!):

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

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

  $scope.allInfos = Informer.allInfos;  
  $scope.remove = Informer.remove;
});

And finally, to render alerts you can use bootstrap's markup directly, or write a very simple directive that encapsulates it. Here I', using the alert directive from 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>

Of course you don't need to use directives from this repo, you can create your own or use raw markup if needed.

Here is a plunker demonstrating a working example: http://plnkr.co/edit/VxAcjHFhxXODFB5iAfyX?p=preview

To sum up:

  • As a rule of thumb don't do DOM manipulation outside of directives
  • Service dealing with the model should be decoupled from model's presentation

I would also advice removing jQuery from a project while learning AngularJS. This way you will quicker get into AngularJS-zen state!

这篇关于AngularJS 线人服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆