如何在 AngularJs 中正确实施:自定义指令在单个页面中多次重用

How to correctly implement in AngularJs: Custom directive reuse several times in single page

我创建了一个带有事件处理程序的自定义指令并使用了 3 次。

<div sl-entity-browser btn_label="Browse supplier" handler="supplier_selection_handler(entity)" />

<div sl-entity-browser btn_label="Browse checker" handler="checker_selection_handler(entity)" />

<div sl-entity-browser btn_label="Browse approving officer" handler="approvar_selection_handler(entity)" />

在我的控制器中:

$scope.supplier_selection_handler = function(entity){
  $scope.selectedSupplier = entity;
}

$scope.checker_selection_handler = function(entity){
  $scope.selectedChecker = entity;
}

$scope.approvar_selection_handler = function(entity){
  $scope.selectedApprovingOfficer = entity;
}

我的指令:

return {
            scope : {
                btnLabel : '@',
                handler: '&'
            },
            restrict: 'AE',
            templateUrl: '/common/sl-entity-browser',
            link: function (scope, elem, attrs) { 

                // expose selected account to the outside world
                scope.selectEntity = function(entity) {
                    return $timeout(function() {
                        return scope.handler({
                            entity: entity
                        });
                    });
                }

            }
        };

HTML 模板:

<button title="browse account"  class="btn btn-primary" data-toggle="modal" data-target="#slEntityModal"> {{ btnLabel }}</button>

<div class="modal fade" id="slEntityModal" tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel" aria-hidden="true">
    <div class="modal-dialog modal-lg" style="width: 90%">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
                <h4 class="modal-title" id="myModalLabel">Browse entities</h4>
            </div>
            <div class="modal-body">
                <div>
                    <div class="row">
                        <div class="input-group pull-right" style="width: 300px">
                            <input class="form-control" placeholder="Search" ng-model="query" />
                            <span class="input-group-addon"><i class="glyphicon glyphicon-search"></i></span>
                        </div>
                    </div>
                    <div class="row">
                        <div class="col-lg-12 col-md-12">
                            <div class="row-top-buffer" style="margin-top: 15px"/>
                            <div class='row' style="border-top: 1px solid #dcdcdc; padding-top: 10px">
                                <div class="col-md-1 col-lg-1"><span style="font-weight: bold; padding-left: 2px;">Acct No</span></div>
                                <div class="col-md-5 col-lg-5"><span style="font-weight: bold; padding-left: 30px;">Name</span></div>
                                <div class="col-md-6 col-lg-6"><span style="font-weight: bold">Address</span></div>
                            </div>
                            <div class="row-top-buffer" style="margin-top: 5px"/>
                            <div class="row" style='max-height: 500px; overflow: auto;'>
                                <div ng-show="!slEntities">Loading entities...</div>
                                <table class="table table-striped table-hover table-bordered">
                                    <thead>
                                    <tr>
                                    </tr>
                                    </thead>
                                    <tbody>
                                    <tr data-dismiss="modal" ng-repeat="entity in entities = (slEntities | filter:query)" style="cursor: pointer" ng-click="selectEntity(entity)">
                                        <td style="width: 100px;">{{entity.accountNo}}</td>
                                        <td style="width: 480px;">{{entity.name}} <span class="label {{entityClass(entity.marker)}} pull-right">{{convert(entity.marker)}}</span></td>
                                        <td>{{entity.address}}</td>
                                    </tr>
                                    <tr ng-show="entities.length == 0"><td colspan="3" align="center">No records found</td></tr>
                                    </tbody>
                                </table>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
            </div>
        </div>
    </div>
</div>

该指令将呈现一个按钮,单击该按钮将显示模式。模态包含 table 项。如果选择了某个项目,将处理模态并且事件应触发定义的正确项。问题是第一个指令实例的事件处理程序(supplier_selection_handler)总是被调用。

我是 AngularsJs 的新手。

提前致谢。

这是因为您的指令(所有指令!)打开的模态是第一个指令的模态。注意到你所有的模态框共享相同的 ID 了吗?和您的按钮的 data-target 共享相同的 ID?由于元素的 ID 是唯一的,因此一旦找到具有该特定 ID 的元素,它将停止搜索具有该 ID 的另一个元素。因此,所有打开模式的按钮都只会打开第一个模式。

我建议您改用 angular-bootstrap's modal,组件本身在 AngularJS 上下文中运行,因此不会出现范围问题。

下面的示例展示了如何创建一个可以使用 angular-bootstrap 模态的指令,我精简了下面的代码以简化演示。

DEMO

索引

  <body ng-controller="Ctrl">

    <button sl-entity-browser 
            btn-label="hello world" 
            handler="messageHandler('This is a message from hello world')"
            class="btn btn-primary">
      Hello World?
    </button>

    <button sl-entity-browser 
            btn-label="Yeah Baby" 
            handler="messageHandler('WEEEE wOoOoOw')"
            class="btn btn-primary">
      Baby?
    </button>

    <button sl-entity-browser 
            btn-label="Boom!"
            handler="messageHandler('This is kaboom boom!')"
            class="btn btn-primary">Kaboom!</button>

  </body>

模态

<div class="modal-header">
    <h3 class="modal-title">I'm a modal!</h3>
</div>
<div class="modal-body">
    {{ btnLabel }}
</div>
<div class="modal-footer">
    <button 
      ng-click="handler()"
      class="btn btn-primary pull-left">
      Click ME!
    </button>
</div>

JAVASCRIPT

(function(angular) {

  var app = angular.module('app', ['ui.bootstrap']);

  app.controller('Ctrl', function($scope, $window) {

    // handler function
    $scope.messageHandler = function(message) {
      $window.alert(message);
    };

  });

  // directive assignment
  app.directive('slEntityBrowser', slEntityBrowser);

  function slEntityBrowser() {
    // directive definition
    return {
      scope: {
        btnLabel: '@',
        handler: '&'
      },
      controller: slEntityBrowserController,
      link: slEntityBrowserLink
    };
  }

  // directive controller
  function slEntityBrowserController($scope, $modal) {

    // create open() method
    // to open a modal
    $scope.open = function() {
      $modal.open({
        scope: $scope,
        templateUrl: 'sl-entity-browser-modal.html'
      });
    };

  }

  // directive link
  function slEntityBrowserLink(scope, elem) {
    // register click handler on the current element
    // to open the modal
    elem.on('click', function() {
      scope.open();
    });
  }

})(window.angular);