AngularJs使用指令切换模板以创建stackoverflow之类的通知

时间:2015-11-15 22:44:54

标签: angularjs angularjs-directive

我试图在AngularJs中创建一个通知系统,就像这里使用的通知一样。当有新评论,回答等时。存档图标会显示一个带有活动数量的红色标记,当我点击它时,它会打开一个包含最后通知的框。

为此,我构建了这个简单的指令来动态加载templateUrl:

HTML:

<li test-alert ref="msg">
    <i class="fa fa-envelope-o"></i>
</li>
<li test-alert ref="bell">
    <i class="fa fa-bell-o"></i>
</li>

指令:

angular
    .module('agApp')
    .directive('testAlert', testAlert)
;

/* @ngInject */
function testAlert() {
    var templateA = '<div>Test template A</div>';
    var templateB = '<div>Test template B</div>';
    return{
        restrict: 'A',
        scope: {
            ref: '@'
        },
        link: function(scope,element,attrs,controller){
            scope.showAlert = false;
            element.on("click", function() {
                if (scope.ref == 'bell') {
                    scope.showAlert = true;
                    element.append(templateA);
                    scope.$apply();
                } else {
                    scope.showAlert = true;
                    element.append(templateB);
                    scope.$apply();
                };
                console.log(scope.ref);
            });
            element.addEventListener("keyup", function(e) {
                if (e.keyCode === 27) {
                    scope.showAlert = false;
                }
            });
        }
    };
}; //end test alert

但我有些问题......

  • 如果我点击图标打开模板,它将会打开,但每次点击它时,它都会附加另一个模板。 ID&#39;喜欢改变(如果它是另一个模板)或什么也不做。
  • 当它打开时,我无法将其关闭。我可以使用&#39;关闭&#39;按钮,但我想在用户点击文档或按esc时关闭/删除模板;
  • 我试图用来关闭Esc&#39;关键,没有用。

我的主要目标是创建一个与stackOverflow中的通知系统类似的通知系统,这是最好的方法吗?我应该使用控制器吗?

编辑:

关闭机制我在妈妈家里使用。它可以工作,但也许可以改进。

run.js

angular
.module('agApp')
.run(runApp);


/* @ngInject */
function runApp($rootScope) {

    document.addEventListener("keyup", function(e) {
        if (e.keyCode === 27) {
            $rootScope.$broadcast("escapePressed", e.target);
        };
    });
    document.addEventListener("click", function(e) {
        $rootScope.$broadcast("documentClicked", e.target);
    });


}; //end run

controller.js

$rootScope.$on("documentClicked", _close);
$rootScope.$on("escapePressed", _close);
function _close() {
    $scope.$apply(function() {
        vm.closeAlert();
    });
};

由于我无法将其用作指令,因此我在控制器内部移动了打开/关闭功能。但它可以以任何其他方式使用,只要它有效,就没有问题。

1 个答案:

答案 0 :(得分:1)

首先,关键事件仅触发可能获得焦点的文档和元素。

指令非常适合您需要多次使用的东西。但即使您将通知系统实施为指令并仅使用一次 - 您也会将其隔离,这通常很好。

很难在不知道更多的情况下提供最佳解决方案,但这里有一个将消息和通知实现为一个指令的示例:

app.directive('notifications',
  function() {

    return {
      restrict: 'E',
      templateUrl: 'template.html',
      scope: {},
      link: function(scope, element, attrs, controller) {

        scope.viewModel = {
          showTemplateA: false,
          showTemplateB: false
        };

        scope.toggleTemplateA = function() {

          scope.viewModel.showTemplateA = !scope.viewModel.showTemplateA;

          scope.viewModel.showTemplateB = false;
        };

        scope.toggleTemplateB = function() {

          scope.viewModel.showTemplateB = !scope.viewModel.showTemplateB;

          scope.viewModel.showTemplateA = false;
        };

      }
    };
  });

它只包含显示和隐藏模板的逻辑。该指令使用如下所示的模板:

<div>
  <i class="fa fa-envelope-o" ng-click="toggleTemplateA()"></i>
  <div ng-show="viewModel.showTemplateA">
    Template A
  </div>
  <br>
  <i class="fa fa-bell-o" ng-click="toggleTemplateB()"></i>
  <div ng-show="viewModel.showTemplateB">
    Template B</div>
</div>

模板使用ng-showng-click绑定到我们的范围函数。通过这种方式,我们让Angular完成工作并且不必混淆element.append等。

用法:

<notifications></notifications>

演示: http://plnkr.co/edit/8M1D5uENjpDoIbb1ZuMR?p=preview

要实现关闭机制,您可以将以下内容添加到指令中:

var close = function () {

  scope.$apply(function () {
    scope.viewModel.showTemplateA = false;
    scope.viewModel.showTemplateB = false;
  });
};

$document.on('click', close);

$document.on('keyup', function (e) {

  if (e.keyCode === 27) {
    close();
  }
});

scope.$on('$destroy', function () {

  $document.off('click', close);
  $document.off('keyup', close);
});

请注意,您现在必须将$document注入指令:

app.directive('notifications', ['$document',
  function($document) {

在切换功能中,您可以调用stopPropagation()以防止在单击图标时执行全局关闭处理程序(在此示例中可能不需要,但很有必要。可能希望它在实际模板中未来?):

scope.toggleTemplateA = function($event) {

          $event.stopPropagation();

ng-click="toggleTemplateA($event)"

演示: http://plnkr.co/edit/LHS4RBE7qtY4yNyEdR16?p=preview