将子组件的元素暴露给子组件

时间:2017-03-29 17:56:13

标签: angularjs angularjs-components

我有一个主要组件来处理我的角度应用程序的工具栏和sidnav。我想在子工具栏(和控制器)中使用工具栏中的div进行自定义,以便他们可以执行更改工具栏标题文本和添加上下文按钮等操作。这感觉有点像转置的相反,其中父组件可以定制子组件的一部分(例如,定制按钮内容的菜单组件)。一个选项是让工具栏由服务管理,但即便如此,我也想不出一个很好的方法来自定义工具栏的内容而不需要构建大量dom元素的大量javascript(其中一件事我总是尽量避免角度。)

1 个答案:

答案 0 :(得分:0)

在Angular 1.6.x components中仅使用隔离范围:

  

组件只控制自己的视图和数据:组件应该   永远不要修改超出自己范围的任何数据或DOM。一般,   在AngularJS中,可以在应用程序的任何位置修改数据   通过范围继承和手表。这很实用,但也可以   当不清楚应用程序的哪个部分时会导致问题   负责修改数据。这就是组件指令的原因   使用隔离范围,因此不需要整类范围操作   可能的。

因此,要完成这项工作,您需要使用指令而不是组件。要包含的div需要是一个指令本身才能更改工具栏指令的父作用域。你要做的是将一个指令转换到另一个指令中,并使用共享范围来改变父范围。

本文对于您要完成的工作来说是一个非常好的资源。我将从这里开始:https://www.airpair.com/angularjs/posts/transclusion-template-scope-in-angular-directives

我更改了该文章中的示例Codepen,以向您展示它的工作原理:http://codepen.io/jdoyle/pen/aJQpYo

如果您在列表中选择项目,则可以看到标题名称更改为所选内容。

angular.module("ot-components", [])

.controller("AppController",($scope)=> {
  //Normally, this data would be wrapped in a service. For example only.
  $scope.header = "Marketing";
  $scope.areas = {
    list: [
      "Floorplan",
      "Combinations",
      "Schedule",
      "Publish"
    ],
    current: "Floorplan"
  };
})

.directive("otList", ()=> {
  return {
    scope: false,  // this is one of the major changes
    template: 
    `<ul class="ot-list">
      <li class="ot-list--item"
        ng-repeat="item in items"
        ng-bind="item"
        ng-class="{'ot-selected': item === selected}"
        ng-click="selectItem(item)">
       </li>
    </ul>`,
    link: (scope, elem, attrs) => {
      scope.items = JSON.parse(attrs.items);
      scope.selected = attrs.selected;

      scope.selectItem = (item) => {
        scope.selected = item;
        scope.$parent.header = item;  // this is the other major change
      };
    }
  };
})

.directive("otSite", ()=> {
  return {
    scope: true,  // another major change
    transclude: true,
    template: 
    `<div class="ot-site">
        <div class="ot-site--head">
          <img class="ot-site--logo" src="//guestcenter.opentable.com/Content/img/icons/icon/2x/ot-logo-2x.png">
        <h1>{{header}}</h1>
        </div>
        <div class="ot-site--menu">
        </div>
        <div class="ot-site--body" ng-transclude>
        </div>
        <div class="ot-site--foot">
          &copy; 2015 OpenTable, Inc.
        </div>
      </div>`     
  };
});