如何定义角度指令,该指令包含一个方法,并且可以通过“ng click”调用



我想定义一个指令,它将首先显示包含按钮的第一个子项。如果我们点击按钮,第二个孩子将取代第一个孩子。

HTML:

<div show-more>
  <div>short <button ng-click="showMore()">click-me to show more</button></div>
  <div>full</div>
</div>

角度:

angular.module("app", [])
.directive("showMore", function() {
  return {
    restrict: 'A',
    scope: {},
    link: function(scope, element, attrs) {
      var children = element.children();
      var short = children[0];
      var full = children[1];
      element.empty().append(short);
      scope.showMore = function() {
        element.empty().append(full);
      };
    }
  };
});

问题是,当我点击按钮时,什么都没有发生。我试了很多,但还是没成功。

您可以在这里看到现场演示:http://jsbin.com/rugov/2/edit

如何修复?

由于您正在更改指令的element的DOM,因此需要重新设置$compile元素,如下所示:

.directive("showMore", function($compile) {
  return {
    restrict: 'A',
    scope: {},
    link: function(scope, element, attrs) {
      var children = element.children();
      var short = children[0];
      var full = children[1];
      element.empty().append(short);
      $compile(element.contents())(scope);
      scope.showMore = function() {
        element.empty().append(full);
      };
    }
  };
});

工作示例

问题是您的指令创建了新的隔离作用域,但ng-click指令被放置在另一个作用域中的元素上。我将通过2个指令来实现您的要求,一个指令取决于另一个指令。

angular.module("app", [])
  .directive("showMoreWrapper", function() {
    return {
      restrict: 'A',
      scope: {},
      controller: function($element) {
        this.showMore = function() {
          var children = $element.children();
          children.eq(0).hide();
          children.eq(1).show();
        };
      },
      link: function(scope, element, attrs) {
        var children = element.children();
        children.eq(1).hide();
      }
    };
  })
  .directive("showMore", function() {
    return {
      restrict: 'A',
      require: '^showMoreWrapper',
      link: function(scope, element, attrs, showMoreWrapper) {
        element.on('click', showMoreWrapper.showMore);
      }
    };
  });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
  <div show-more-wrapper>
    <div>short
      <button show-more>click-me to show more</button>
    </div>
    <div>full</div>
  </div>
</div>

我会采用自定义组件方法

angular.module("app", [])
.directive("showMore", function() {
  return {
    restrict: 'E',
    scope: {},
    transclude: true,
    template: '<button ng-click="toggle()">{{title}}</button><div ng-transclude></div>',
    controller: function($scope) {
      var self = this;
      $scope.title = "Show More";
      
      $scope.toggle = function() { 
        self.short.show = !self.short.show;
        self.full.show = !self.full.show;
        $scope.title = self.short.show ? "Show More" : "Show Less";
      };
      this.addShort = function(short) {
        self.short = short;
      };
      this.addFull = function(full) {
        self.full = full;
      };
    }
  };
})
.directive("short", function() {
  return {
    restrict: 'E',
    scope: {},
    require: '^showMore',
    transclude: true,
    template: '<div ng-if="show" ng-transclude></div>',
    link: function(scope, element, attrs, showMoreCtrl) {
      scope.show = true;
      showMoreCtrl.addShort(scope);
    }
  };
})
.directive("full", function() {
  return {
    restrict: 'E',
    scope: {},
    require: '^showMore',
    transclude: true,
    template: '<div ng-if="show" ng-transclude></div>',
    link: function(scope, element, attrs, showMoreCtrl) {
      scope.show = false;
      showMoreCtrl.addFull(scope);
    }
  };
});
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular.min.js"></script>
<div ng-app="app">
      <show-more>
        <short>short</short>
        <full>full</full>
      </show-more>
</div>

最新更新