【问题标题】:Issue in angular-bootstrap directive while trying to access scope尝试访问范围时 angular-bootstrap 指令中的问题
【发布时间】:2015-12-12 19:25:22
【问题描述】:

我已将https://github.com/angular-ui/bootstrap 用于手风琴,但使用此指令时我遇到了范围问题。只有在手风琴内部声明 ngController 时,它才允许使用范围。

请访问以下两个 Plunker 链接,您就会明白我的意思:

示例 1http://plnkr.co/edit/Fb4UauWWmHOnTyjMPFBo

index.html

<!doctype html>
<html ng-app="plunker">
<head>
  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.js"></script>
  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular-animate.js"></script>
  <script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.13.4.js"></script>
  <script src="script.js"></script>
  <link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>  
  <div ng-controller="AccordionDemoCtrl">
    <accordion>
      <accordion-group is-open="status.open">
        <accordion-heading>
          Accordian - Click me <i class="pull-right glyphicon" ng-class="{'glyphicon-chevron-down': status.open, 'glyphicon-chevron-right': !status.open}"></i>
        </accordion-heading>
        <div>
          <input type="checkbox" ng-model="select" ng-click="checkAll()" /> Check me
        </div>
      </accordion-group>
    </accordion>
  </div>
</body>
</html>

script.js

var app = angular.module('plunker', ['ui.bootstrap']);
app.controller('AccordionDemoCtrl', function($scope) {
  $scope.checkAll = function() {
    alert($scope.select);
  };
});

示例 2http://plnkr.co/edit/ljEMUnTqPBqUyub5eEB7

index.html

<!doctype html>
<html ng-app="plunker">
<head>
  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.js"></script>
  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular-animate.js"></script>
  <script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.13.4.js"></script>
  <script src="script.js"></script>
  <link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
  <accordion>
    <accordion-group is-open="status.open">
      <accordion-heading>
        Accordian - Click me <i class="pull-right glyphicon" ng-class="{'glyphicon-chevron-down': status.open, 'glyphicon-chevron-right': !status.open}"></i>
      </accordion-heading>
      <div ng-controller="AccordionDemoCtrl">
        <input type="checkbox" ng-model="select" ng-click="checkAll()" /> Check me
      </div>
    </accordion-group>
  </accordion>
</body>
</html>

script.js

var app = angular.module('plunker', ['ui.bootstrap']);
app.controller('AccordionDemoCtrl', function($scope) {
  $scope.checkAll = function() {
    alert($scope.select);
  };
});

【问题讨论】:

    标签: angularjs angularjs-directive angular-bootstrap


    【解决方案1】:

    我找到了解决办法:

    我们可以从函数本身传递值,而不需要使用 $scope 访问值。

    演示:http://plnkr.co/edit/fZZrDN4e8kbvimR2Wzya

    index.html

    <!doctype html>
    <html ng-app="plunker">
    
    <head>
      <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.js"></script>
      <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular-animate.js"></script>
      <script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.13.4.js"></script>
      <script src="script.js"></script>
      <link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
    </head>
    
    <body>
    
      <div ng-controller="AccordionDemoCtrl">
        <accordion>
          <accordion-group is-open="status.open">
            <accordion-heading>
              Accordian - Click me <i class="pull-right glyphicon" ng-class="{'glyphicon-chevron-down': status.open, 'glyphicon-chevron-right': !status.open}"></i>
            </accordion-heading>
            <div>
              <input type="checkbox" ng-model="select" ng-click="checkAll(select)" /> Check me
            </div>
          </accordion-group>
        </accordion>
      </div>
    </body>
    
    </html>
    

    script.js:

    var app = angular.module('plunker', ['ui.bootstrap']);
    app.controller('AccordionDemoCtrl', function($scope) {
      $scope.checkAll = function (select) {
        alert(select);
      };
    });
    

    【讨论】:

      【解决方案2】:

      发生这种情况是因为 Angular Bootstrapdirective "accordionGroup" 的 scopeisolated 并且 controller "AccordionDemoCtrl" 的 $scope 被继承在“directive”中使用require

      因此,对于 Example1,当您尝试访问 AccordionDemoCtrl 内部的 AccordionDemoCtrl 绑定时,accordian group directive 很容易访问。但由于select 位于localaccordian group directivelocal 中,因此无法在控制器中访问。

      因此,对于 Example2,当您尝试访问 AccordionDemoCtrlinside accordian group directive$scope 绑定时,它很容易访问,因为控制器位于本地 scope for the @ 987654344@。

      请参考directive to directive Comm

      这是来自 Angular Bootstrap Library for Accordian 的代码

      .directive('accordion', function () {
        return {
          restrict:'EA',
          controller:'AccordionController',
          transclude: true,
          replace: false,
          templateUrl: 'template/accordion/accordion.html'
        };
      })
      
      // The accordion-group directive indicates a block of html that will expand and collapse in an accordion
      .directive('accordionGroup', function() {
        return {
          require:'^accordion',         // We need this directive to be inside an accordion
          restrict:'EA',
          transclude:true,              // It transcludes the contents of the directive into the template
          replace: true,                // The element containing the directive will be replaced with the template
          templateUrl:'template/accordion/accordion-group.html',
          scope: {
            heading: '@',               // Interpolate the heading attribute onto this scope
            isOpen: '=?',
            isDisabled: '=?'
          },
          controller: function() {
            this.setHeading = function(element) {
              this.heading = element;
            };
          },
          link: function(scope, element, attrs, accordionCtrl) {
            accordionCtrl.addGroup(scope);
      
            scope.$watch('isOpen', function(value) {
              if ( value ) {
                accordionCtrl.closeOthers(scope);
              }
            });
      
            scope.toggleOpen = function() {
              if ( !scope.isDisabled ) {
                scope.isOpen = !scope.isOpen;
              }
            };
          }
        };
      })
      
      // Use accordion-heading below an accordion-group to provide a heading containing HTML
      // <accordion-group>
      //   <accordion-heading>Heading containing HTML - <img src="..."></accordion-heading>
      // </accordion-group>
      .directive('accordionHeading', function() {
        return {
          restrict: 'EA',
          transclude: true,   // Grab the contents to be used as the heading
          template: '',       // In effect remove this element!
          replace: true,
          require: '^accordionGroup',
          link: function(scope, element, attr, accordionGroupCtrl, transclude) {
            // Pass the heading to the accordion-group controller
            // so that it can be transcluded into the right place in the template
            // [The second parameter to transclude causes the elements to be cloned so that they work in ng-repeat]
            accordionGroupCtrl.setHeading(transclude(scope, function() {}));
          }
        };
      })
      

      【讨论】:

      • 谢谢@Sahilgupta,我已经阅读了你提到的链接,但我仍然没有得到任何解决方案。这很难实现吗?我应该更改用于手风琴的指令吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多