在 AngularJS 中,Controller 之間可以共用的代碼我們通常抽出來寫成一個 Service。全局 Alert 消息系統就是一個很好的例子,比如“用戶註冊成功”、“添加商品成功”,每個 Controller 都有機會發出通告,這一部分功能應該寫成獨立模塊。

Angular-UI Bootstrap 項目提供了一系列的模塊,將 Bootstrap 中的 component 轉換為原生的 Angular directives,如果你正在同時使用 Bootstrap 和 AngularJS,那麼強烈建議你使用它。

angularui-alert

在 Angular-UI Bootstrap 的文檔里,有下面的例子來創建一個 alert:

View:

<div ng-controller="AlertDemoCtrl">
  <alert ng-repeat="alert in alerts" type="alert.type" close="closeAlert($index)">{{alert.msg}}</alert>
  <button class='btn' ng-click="addAlert()">Add Alert</button>
</div>

Controller:

function AlertDemoCtrl($scope) {
  $scope.alerts = [
    { type: 'error', msg: 'Oh snap! Change a few things up and try submitting again.' }, 
    { type: 'success', msg: 'Well done! You successfully read this important alert message.' }
  ];
 
  $scope.addAlert = function() {
    $scope.alerts.push({msg: "Another alert!"});
  };
 
  $scope.closeAlert = function(index) {
    $scope.alerts.splice(index, 1);
  };
}

假如說我們想要從很多不同的 Controller 發出 alert,那麼像上面那樣寫就會導致跨 Controller 地調用函數,這屬於 bad practice。我們將 alert 抽出來寫成一個 Service ——

alertService:

'use strict';
/* services.js */
 
// 別忘記將本 service 依賴注入到你的 app
var appServices = angular.module('myApp.services', []);
 
appServices.factory('alertService', function($rootScope) {
    var alertService = {};
 
    // 創建一個全局的 alert 數組
    $rootScope.alerts = [];
 
    alertService.add = function(type, msg) {
      $rootScope.alerts.push({'type': type, 'msg': msg, 'close': function(){ alertService.closeAlert(this); }});
    };
 
    alertService.closeAlert = function(alert) {
      alertService.closeAlertIdx($rootScope.alerts.indexOf(alert));
    };
 
    alertService.closeAlertIdx = function(index) {
      $rootScope.alerts.splice(index, 1);
    };
 
    return alertService;
});

下面這段 HTML 可以放到你的 index.html 模板里,或者 include 到所有的頁面。
View:

<alert ng-repeat="alert in alerts" type="alert.type" close="alert.close()">
    <span data-ng-bind-html="alert.msg"></span>
</alert>

最後,創建一個全局的 alert 就只需要在你的任何 Controller 裡面調用 alertService.add() 即可,非常方便。

var UserCtrl = ['$scope', 'alertService',
    function(    $scope,   alertService) {
        alertService.add('warning', '這是一個警告消息!');
        alertService.add('error', "這是一個出錯消息!");
 
        $scope.editProfile = function() {
            //...do something
            alertService.add('success', '<h4>成功!</h4> 你的個人資料已經修改。');
        }
}];

查看 Demo