Angular 指令:按钮微调器

Angular Directive: Button Spinner

我创建了一个指令,它的行为就像当你点击按钮时它会显示微调器或加载器,它向用户显示正在进行的事情,比如 API 调用或移动到另一个页面,我正面临以下问题:

  1. 如果页面上使用了多个指令,它会为两个按钮显示微调器而不是单击按钮,我希望它只为单击按钮显示

  2. 在某些情况下,单击事件绑定了三次,因为按钮内部使用了三个 span 来显示微调器,事件传播存在一些问题

指令代码如下:

(function () {
    'use strict';

    angular
        .module('app.base')
        .directive('buttonSpinner', directiveFunction)
        .controller('btnController', ControllerFunction);


    // ----- directiveFunction -----
    directiveFunction.$inject = [];

    /* @ngInject */
    function directiveFunction() {

        var directive = {
            restrict: 'E',
            scope: {
              label: "@",
              available: "="
            },
            controller: 'btnController',
            controllerAs: 'vm',
            replace: true,
            transclude: true,
            template:
              '<button ng-disabled="vm.isDisabled">'
                + '<span ng-hide="vm.isClicked">{{label}}</span>'
                + '<div class="spinner" ng-show="vm.isClicked">'
                +   '<span class="bounce1"></span>'
                +   '<span class="bounce2"></span>'
                +   '<span class="bounce3"></span>'
                + '</div>' +
              '</button>'
        };

        return directive;
    }

    // ----- ControllerFunction -----
    ControllerFunction.$inject = [ '$scope' ];

    /* @ngInject */
    function ControllerFunction( $scope ) {

        var vm = this;
        vm.isClicked = false;
        $scope.$on('APICALLED', function(event, data){
          vm.isClicked = data.done;
          if( data.elem ) {
            angular.element(document.getElementById(data.elem))[0].disabled = true;
          } else {
            vm.isDisabled = data.disable;
          }
        });
    }

})();

使用方法:

在视图中:

<button-spinner class="btn btn-primary btn-block btn-lg" type="submit" ng-click="vm.notifyMe($event)" label="Notify Me" available="vm.notify.is" id="notifyMeBtn"></button-spinner>

在控制器中:

显示微调器:

$rootScope.$broadcast('APICALLED', {'done': true, 'disable': true});

隐藏微调器:

 $rootScope.$broadcast('APICALLED', {'done': false, 'disable': false});

您的问题与您的 $broadcast's 有关,因此它是模式问题。 $rootScope.$broadcast() 根本不是一个好的解决方案。例如)您需要手动销毁 $rootScope.$broadcast.$on() 绑定。只需将一个唯一的范围变量解析到指令中,如 loading。对于每个加载过程,此范围参数可以由控制器本身处理:

/* @ngInject */
function directiveFunction() {

    var directive = {
        restrict: 'E',
        scope: {
            label: "@",
            available: "=",
            loading: "="
        },
        controller: 'btnController',
        controllerAs: 'vm',
        replace: true,
        transclude: true,
        template:
        '<button ng-disabled="vm.isDisabled">'
        + '<span ng-hide="vm.isClicked">{{label}}</span>'
        + '<div class="spinner" ng-show="vm.loading">'
        +   '<span class="bounce1"></span>'
        +   '<span class="bounce2"></span>'
        +   '<span class="bounce3"></span>'
        + '</div>' +
        '</button>'
    };

    return directive;
}

查看

<button-spinner class="btn btn-primary btn-block btn-lg"
                type="submit"
                ng-click="vm.notifyMe($event)"
                loading="vm.isLoading"
                label="Notify Me"
                available="vm.notify.is"
                id="notifyMeBtn"></button-spinner>