【问题标题】:Accessing component controller from transcluded HTML从嵌入的 HTML 访问组件控制器
【发布时间】:2017-06-06 19:57:01
【问题描述】:

Plunker,因为 sn-p 编辑器今天不喜欢我。

快速信息

在使用 Angular 1.6 时,我正在努力使用 .component() 代替 .directive(),以使自己更多地了解 Angular 2 使用的设计模式类型。问题是我不能使用任何对 @987654324 的引用@ 或 $tab(这些相应组件的控制器)。使用{{$tab.tabsCtrl.nothing}}{{$tabs.nothing}} 不会输出任何内容。

请注意:这不是我的实际情况,但它确实与我实际做的事情有一个共同的问题。

我四处搜索,得到了很多关于 Angular 2 组件的结果,但如果我说实话,它基本上是希腊语。

代码参考(sn-p编辑器不工作,仅供参考)

// Code goes here
angular.module('main.app', [])
  .component('tabs', {
    controller: function($http) {
      this.tabs = [];
      this.nothing = 'nada';
      this.addTab = function(tab) {
        this.tabs.push(tab);
      }; //end addTab
      this.selectTab = function(tab) {
        this.tabs.map(function(item) {
          item.selected = false;
        });
        var selected = this.tabs.filter(function(item) {

          return item === tab;
        });
        if (selected.length) selected[0].selected = true;
      }; //End selectTab
    },
    template: '<ul class="nav nav-tabs nav-justify justify-content-center"><li class="nav-item" ng-repeat="tab in $tabs.tabs" ><a href="#" ng-click="$tabs.selectTab(tab)" class="nav-link" ng-class="{\'active\':tab.selected}">{{tab.tabTitle}}</a></li></ul><div class="tabs-content" ng-transclude></div>',
    transclude: true,
    controllerAs: '$tabs'
  })
  .component('tab', {
    require: {
      'tabsCtrl': '^tabs'
    },
    bindings: {
      'tabTitle': '@',
      'selected': '<'
    },
    controller: function() {
      this.$onInit = function() {
        this.selected = this.selected || false;
        this.tabsCtrl.addTab(this);
      }; //end $onInit
    },
    transclude: true,
    controllerAs: '$tab',
    template: '<div class="tab" ng-show="$tab.selected"><div ng-transclude></div></div>'
  })
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.6.0/angular.js"></script>
<tabs>
  <tab tab-title="First Tab" selected="true">
    <div class="jumbotron">
      <h3>Lorem ipsum.</h3>
      <p class="lead">Lorem ipsum dolor sit amet.</p>
      <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Iusto, in!</p>
    </div>
    some other text
  </tab>
  <tab tab-title="Second Tab">
    <strong>With a header!</strong>
    <div class="row">
      <div class="col-6 bg-primary">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nisi, quam, quod, optio qui cum rerum vel eos rem aspernatur quia maxime incidunt numquam ipsum eum neque dicta distinctio. Minus, itaque.</div>
      <div class="col-6 bg-danger">Reprehenderit, numquam, rerum, reiciendis neque adipisci provident ea quo illo praesentium inventore fuga quisquam ducimus? Ipsum, autem, illo ullam corporis incidunt ad labore accusantium tempora officia quas quia eaque facere.</div>
    </div>
  </tab>
  <tab tab-title="Potato Tab">
    <h3>Big books {{$tabs.nothing||'nah'}}</h3>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Iste quos assumenda vero fugiat officia pariatur consequatur deserunt quisquam veniam nemo?</p>
    <p>Fugiat, error, impedit, accusantium consequuntur beatae facere esse voluptatum enim animi porro commodi modi cupiditate aliquam iure ipsa. A, officiis!</p>
    <p>Architecto velit quod explicabo laborum reprehenderit culpa tempora facilis minima eum. Natus aliquid eaque laboriosam accusamus dolor hic similique ad.</p>
  </tab>
</tabs>

谢谢,以防我以后忘记说!

【问题讨论】:

    标签: javascript angularjs angular-components


    【解决方案1】:

    被嵌入的范围将是指令的隔离范围的子范围。

    由于组件使用隔离作用域,因此您不能仅通过 {{$tabs.nothing}} 来使用原型继承。如果$tabs 是通过$rootScope 公开的,或者层次结构中选项卡上方的任何其他非隔离范围(在您的示例中只有ng-app,所以只有$rootScope),它会起作用。

    您可以手动遍历作用域链。

    根据您的示例:

    1. 当前范围将是 tab 指令的嵌入子范围
    2. 第一个 $parent 将是隔离 tab 范围
    3. 第二个$parent 将是tabs 指令的嵌入子范围
    4. 第三个$parent 将是隔离tab 范围

    这给出了:

    {{$parent.$parent.$parent.$tabs.nothing}}
    

    演示: http://plnkr.co/edit/jpTGVKWKEQlmGYpaeqtZ?p=preview

    在大多数情况下,这并不是一个真正可行的解决方案。通过服务公开转入内容所需的功能可能更好。

    在不了解实际用例的情况下很难给出更好的解决方案。

    【讨论】:

    • 我想我明白了你写的东西,但让我仔细检查一下:如果我想使用 $tab 范围内的信息(在一些 @ 之后添加的属性) 987654337@ 请求完成),$parent.someProperty 可以访问吗?在您自己看来,改用.directives 会更容易吗?
    • 是的,这是正确的。像这样(使用 $timeout 而不是 $http):plnkr.co/edit/i55wN97awWrkSFY25zf1?p=preview。我会坚持component。我个人总是尝试将隔离范围与directives 一起使用,因此不会有任何区别。我也从不使用$parent。我会公开你需要的嵌入内容,以便能够通过 tabService 或类似方式访问,以明确这是任何人都可以作为公共 api 注入和使用的东西。
    • 好吧。非常感谢@tasseKATT。你很有帮助。
    猜你喜欢
    • 1970-01-01
    • 2017-03-10
    • 2014-05-21
    • 1970-01-01
    • 2016-02-20
    • 1970-01-01
    • 1970-01-01
    • 2018-01-16
    • 2017-10-24
    相关资源
    最近更新 更多