AngularJS复合材料组件

时间:2013-04-22 19:32:12

标签: angularjs angularjs-directive angularjs-scope

我正在尝试创建一个包含多个子组件的组件。我正在创建一个指令集合,我的团队中的其他开发人员可以使用它来创建自定义搜索表单。例如,他们会创建如下标记:

<search-panel name="myCustomSearch">
    <search-field name="dates" type="dateRange"></search-field>
    <search-field name="categories" type="categorySelector" data="{{categories}}"></search-field>
</search-panel>

我有一个搜索面板指令和几个搜索字段指令。搜索面板充当容器,每个搜索字段都提供特定类型的字段(日期范围,提前输入,类别选择器等)。每个搜索字段在其范围内都有一个value属性,我试图找到一种方法让父搜索面板指令在其范围内具有一个属性,该属性包含所有子搜索字段的键值集合。

我有两个指令正确呈现,但我不知道如何让搜索面板知道/有权访问所有子组件。

4 个答案:

答案 0 :(得分:2)

您可以在search-field指令中使用search-panel

要求require:'^searchPanel'控制器

然后在链接函数中你将有一个指向该控制器的链接,因此这些指令可以将自己添加到某个数组中(我认为每个搜索字段都有其独立的范围):

link: function(scope, elem, attrs, spCtrl) {
  spCtrl.fields.push({name: attrs.name, scope: scope});
}

(当然,你可以添加不是整个范围,而是添加一些对象,然后注意更改并更新该对象的值字段。

答案 1 :(得分:0)

这里的基本思想是在两者之间创建一个通用控制器,并在指令链接中将它们链接起来。

创建指令时,您可以将控制器传递给第四个参数:

app.directive('myDirective', function(){
  return {
    scope: true,
    link: function postLink( scope, element, attrs, ctrls ){
      //check ctrls for common link
    }
  }
}

在angularui / bootstrap项目中创建的一个优秀示例是 Tabs Directive ,它有一个公共控制器将它们连接起来作为开始的位置的示例。

希望这有帮助。

答案 2 :(得分:0)

Mark Rajcok在这里有一个很好的stackoverflow答案:

AngularJS directive controllers requiring parent directive controllers?

链接到这个非常清晰的jsFiddle:http://jsfiddle.net/mrajcok/StXFK/

<div ng-controller="MyCtrl">
    <div screen>
        <div component>
            <div widget>
                <button ng-click="widgetIt()">Woo Hoo</button>
            </div>
        </div>
    </div>
</div>

JavaScript在jsFiddle中。

答案 3 :(得分:0)

我的复合组件实现(多个转录指令)基于以下想法:

  • 使用一个指令
  • 捕获子组件$ transclude
  • 使用另一个指令输出此子组件

现场演示http://nickholub.github.io/angular-composite-component/#/

演示源代码https://github.com/nickholub/angular-composite-component

指令源代码https://github.com/nickholub/angular-composite-component/blob/master/app/directive/angular-composite-component.js

<div cs-composite>
    <div cs-section="header">
        Composite Component Header
    </div>
    <div cs-section="footer">
        Composite Component Footer
        <div>Random Value: {{randomValue}}</div>
        <div>Percentage: {{percentage}}%</div>
    </div>
</div>

捕获内容的指令

.directive('csSection', function () {
    return {
      transclude: 'element',
      priority: 100,
      require: '^csComposite',
      link: function (scope, element, attrs, ctrl, $transclude) {
        var directiveTransclude = {
          id: attrs.csSection,
          transclude: $transclude,
          element: element
        };

        ctrl.registerTransclude(directiveTransclude);
      }
    };
  })

输出内容的指令

.directive('csTransclude', function () {
    return {
      transclude: true,
      link: function (scope, element, attrs) {
        var id = attrs.csTransclude;
        var directiveTransclude = scope.transcludes[id];
        if (directiveTransclude) {
          var selectedScope = scope.$new();
          directiveTransclude.transclude(selectedScope, function (clone) {
            element.append(clone);
          });
        }
      }
    };
  })