将嵌套指令的内容转换为外部指令

时间:2016-05-20 14:02:27

标签: angularjs angularjs-directive

我想创建一个新的AngularJS指令(outer-directive)来包装一些内容(例如html或其他指令),并在左侧动态创建一个小导航。

我没有让这个样本运行。 content-section指令仅用于在左侧菜单中对content指令进行分组,不需要任何标记。 content指令仅在有效时才会在outer-directive占位符中显示其被转换的内容。

任何人都有想法或提示如何使用AngularjS 1.5来解决这个问题?

伪代码中的示例:



<outer-directive>
  <content-section heading="Section 1">
    <content heading="Content 1 in Section 1">
      <!-- some HTML or other directives, etc -->
    </content>
    <content heading="Content 2 in Section 1">
      <!-- some HTML or other directives, etc -->
    </content>
  </content-section>
  <content-section heading="Section 2">
    <content heading="Content 1 in Section 2">
      <!-- some HTML or other directives, etc -->
    </content>
  </content-section>
</outer-directive>
&#13;
&#13;
&#13;

指令模板:

&#13;
&#13;
<div class="row">
  <div class="col-sm-3">
    <!-- some kind of left side menu (want to use uib-accordion directive here) -->
    <ul>
      <li ng-repeat="contentSection in contentSections">
        <h3>{{contentSection.heading}}</h3>
        <ul>
          <li ng-repeat="content in contentSection">
            <a href ng-click="showContent(content.$id)">{{content.heading}}</a>
          </li>
        </ul>
      </li>
    </ul>
  </div>
  <div class="col-sm-9">
    <!-- show active content here with ng-if -->
    <ng-transclude></ng-transclude>
  </div>
</div>
&#13;
&#13;
&#13;

指令伪代码:

&#13;
&#13;
angular.module('myApp')
    .directive('outerDirective',
    [
        function() {
            return {
                restrict: 'E',
                transclude: true,
                replace: true,
                templateUrl: 'outer-template.html',
                controller: [
                    '$scope',
                    function($scope) {
                        $scope.contentSections = [];

                        this.addContentSection = function(contentSectionScope) {
                            var that = this;
                            $scope.contentSections.push(contentSectionScope);

                            contentSectionScope.$on('$destroy',
                                function(event) {
                                    that.removeContentSection(contentSectionScope);
                                });
                        };

                        this.removeContentSection = function(contentSectionScope) {
                            var index = $scope.contentSections.indexOf(contentSectionScope);
                            if (index !== -1) {
                                $scope.contentSections.splice(index, 1);
                            }
                        };
                      
                      // ...
                    }
                ]
            }
        }
    ])
    .directive('contentSection',
    [
        function() {
            return {
                restrict: 'E',
                require: '^outerDirective',
                transclude: true,
                replace: true,
                //template: '',
                scope: {
                    heading: '@'
                },
                controller: [
                    '$scope',
                    function($scope,) {
                        $scope.contents = [];

                        this.addContent = function (contentScope) {
                            var that = this;
                            $scope.contents.push(contentScope);

                            contentScope.$on('$destroy',
                                function (event) {
                                    that.removeContent(contentScope);
                                });
                        };

                        this.removeContent = function (contentScope) {
                            var index = $scope.contents.indexOf(contentScope);
                            if (index !== -1) {
                                $scope.contents.splice(index, 1);
                            }
                        };
                    }
                ],
                link: function (scope, element, attrs, outerCtrl) {
                    outerCtrl.addContentSection(scope);
                }
            }
        }
    ])
.directive('content',
    [
        function () {
            return {
                restrict: 'E',
                require: '^contentSection',
                transclude: true,
                template: '<div ng-transclude></div>',
                scope: {
                    heading: '@'
                },
                controller: [
                    '$scope',
                    function ($scope) {
                        
                    }
                ],
                link: function (scope, element, attrs, contentSectionCtrl) {
                    contentSectionCtrl.addContent(scope);
                }
            }
        }
    ]);;
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:1)

Angular UI's "Tabs" directive solves this problem.

在你的情况下,你会做这样的事情:

angular.module('myApp', ['ui.bootstrap']);

您的HTML将是:

<body ng-app="myApp">
<uib-tabset template-url="custom-tabset-template.html">
  <uib-tab heading="Section 1">
    <!-- some HTML or other directives, etc -->
    Section 1 Content
  </uib-tab>
  <uib-tab heading="Section 2">
    <!-- some HTML or other directives, etc -->
    Section 2 Content
  </uib-tab>
  <uib-tab heading="Section 3">
    <!-- some HTML or other directives, etc -->
    Section 3 Content
  </uib-tab>
</uib-tabset>
</body>

custom-tabset-template.html将是:

<div class="row">
  <!-- You can use uib-accordion directive here. In that case you would 
   have to replace the heading attr on the tab with a nested 
   uib-tab-heading element inside each tab -->
  <ul class="col-sm-3" ng-transclude></ul>
  <div class="col-sm-9 tab-content">
    <div class="tab-pane"
      ng-repeat="tab in tabset.tabs"
      ng-class="{active: tabset.active === tab.index}"
      uib-tab-content-transclude="tab">
    </div>
  </div>
</div>

here is a working plunker

享受。