2

参考

参考plunker:http ://plnkr.co/edit/otv5mVVQ36iPi3Mp0FYw?p=preview

问题说明

假设我们有两个指令,first-directive并且second-directive. 现在假设我们只能访问first-directive我们希望包装second-directive的对象,并将我们自己的操作属性传递给它。

app.directive('firstDirective', function() {
  return {
    scope: true,
    priority: 1000,
    transclude: true,

    template: function(element,attributes){
      console.log('template')
      return '<second-directive two="{{one}}"></second-directive>'
    },

    compile: function(element,attributes) {
      console.log('compile')
      return {
        pre: function(scope){
          scope.one = 'foo'
            console.log('cpre')
        },
        post: function(scope){
          scope.one = 'foo'
            console.log('cpost')
        },
      }
    },

    controller: ['$scope','$attrs',function($scope,$attrs){
      console.log('controller');
      $scope.one = 'foo';
    }],
  }
})

app.directive('secondDirective',function(){
  return {
    template: function (element,attributes){
      console.log(attributes.two) //{{one}} not 'foo' or 'test'
      return 'Hello {{two}}'
    }
  }
});    

first-directive被称为如下:

<first-directive one='test'></first-directive>

console.log 输出如下:

template
compile
{{one}}
controller
cpre
cpost

所以从这里我了解到模板是在编译之前调用的。这在我的新手眼中很奇怪,因为无论如何都无法通过编译、控制器、前置或后置链接来操纵模板函数传回的值!

问题是这样的:

如何second-directive使用我想要的动态属性值调用 ?请记住,这second-directive是完全独立的,我们不能在那里添加代码。

PS - 我有一个可能的想法是调用第二个指令如下:

template: function(element,attributes){
  console.log('template')
  var explicit = ???? /* how to access scope? */
  return '<second-directive two="'+ explicit +'"></second-directive>'
},

或者

template: function(element,attributes){
  console.log('template')
  return $interpolate('<second-directive two="{{one}}"></second-directive>')(scopeObj) /* how does one access scopeObj with current scope values here? */
},

然而,再一次,我不确定如何在调用任何其他函数之前将值传递给第一指令。控制器可以访问 $scope,它被称为 AFTER 模板。

非常感谢您的建议。

4

5 回答 5

0

你写了第二个指令吗?

<second-directive two="'+ explicit +'"></second-directive>

要使上述代码正常工作,您需要在第二个指令中设置隔离范围对象,请查看下面的 plunkr。

http://plnkr.co/edit/YP2h3MOhsrjN5sLUNQs6?p=preview

于 2015-06-16T00:31:13.070 回答
0

我正在使用您的问题来学习,但我能够找到这个,这可能对您有用:

app.directive("tryThis", function($compile){
    return{
        scope: {
          one: '@',
        },
        link: function(scope, element){
            var template = '<second-directive two="'+scope.one+'"></second-directive>';
            var linkFn = $compile(template);
            var content = linkFn(scope);
            element.append(content);
        }
    }
});

Plunkr 在这里,注意test现在登录到控制台而不是{{one}}. 如果 secondDirective 被赋予一个独立的范围,test则将显示在屏幕上。

链接还帮助我从概念上理解您面临的问题,为“编译期间没有范围”步骤的问题提供一些背景信息 - 我不确定是否有解决方法。

于 2015-06-16T00:39:00.980 回答
0

好吧,如果您只想将数据从第一个指令传递到第二个指令模板,那么您可以使用
this.fromFirstDir = "you can pass from here"在第一个指令控制器中添加动态属性

第一个指令控制器:

controller: ['$scope','$attrs',function($scope,$attrs){
      console.log('controller');
      $scope.one = 'foo';

      this.fromFirstDir = "you can pass from here"
    }],
  }

然后使用第二个指令中的require属性用于第一个指令控制器,您可以使用传递给链接函数的控制器从第二个指令的链接函数访问此动态属性。最后将这些属性分配给传递给链接函数的本地范围。

app.directive('secondDirective',function(){
  return { 
    scope: {twoData : '@twoData'},
    require : '^firstDirective',
    template: function (element,attributes){
      console.log(attributes.two) //{{one}} not 'foo' or 'test'
      return 'Hello <b>{{fromFirstDir}}</b>'
    },
    link : function(scope,element,attr,firstDirCtrl){
      console.log("===",firstDirCtrl.fromFirstDir) 
      scope.fromFirstDir = firstDirCtrl.fromFirstDir;
    }
  }
});

这样,这些动态属性可用于您的第二个指令。

这是最后的小提琴

希望这会帮助你。

于 2015-06-16T06:01:16.170 回答
0

您不能(不能)访问模板内的范围(因为当时没有范围)。该模板用于创建一个或多个元素,然后将它们链接到一个范围(在实例化它们的控制器之后 - 如果有的话)。

有很多方法可以在指令之间传递值,每种方法都最适合特定目的。最简单的(但不一定是最好的,取决于您的用例详细信息)是在 wrapper 指令的范围内分配一个值,然后让内部指令从范围内读取它:

<!-- HTML -->
<one for-two="{{test}}"></one>

// JS
angular.
  module('myApp', []).
  directive('one', oneDirective).
  directive('two', twoDirective);

function oneDirective() {
  return {
    restrict: 'E',
    scope: true,
    link: function onePostLink(scope, elem, attrs) {
      scope.two = attrs.forTwo;
    },
    template: '<two></two>'
  };
}

function twoDirective() {
  return {
    restrict: 'E',
    template: 'Hello, {{two}} !'
  };
}
于 2015-06-16T12:27:37.693 回答
0

您有transclude: true但没有在模板中使用它。你不能只使用这个标记并拥有第一个指令使用的模板<ng-transclude>吗?你有scope: true,所以你可以从父/控制器操作属性,并且更改将传播到两个指令。

标记

<first-directive one="test">
    <second-directive two="test"></second-directive>        
</first-directive>

第一指令的模板

template: `<div>
               my first directive content
               <ng-transclude></ng-transclude>
           </div>`;

https://docs.angularjs.org/api/ng/directive/ngTransclude

于 2016-05-12T17:08:03.300 回答