【问题标题】:I can pass a scope variable into a directive's link function, but not the compile function, angular我可以将范围变量传递给指令的链接函数,但不能传递给编译函数,角度
【发布时间】:2015-05-12 07:52:40
【问题描述】:

我正在使用 ng-repeat,我需要将范围变量传递给指令的编译函数。我知道如何使用链接功能,但不知道如何使用编译功能。

我的 html 看起来像:

    <div ng-repeat="item in chapter.main">
      <block type="item.type"></block>
    </div>

不管项目是什么,我们都说 item.type="blah"。 那么这个链接功能就可以正常工作了

app.directive('block', function() {
  return {
      restrict: 'E',
      link: function(scope, element, attributes){
            scope.$watch(attributes.type, function(value){
                console.log(value); //will output "blah" which is correct
            });

        }
  }
});

但是我不能对编译做同样的事情?

app.directive('block', function() {
  return {
      restrict: 'E',
      compile: function(element, attrs, scope) {
        scope.$watch(attrs.type, function(value){
             console.log(value);
         });
      }
  }
});

我得到的错误是“无法读取未定义的属性 $watch”..

这就是我希望我的指令的样子:

app.directive('block', function() {
  return {
      restrict: 'E',
      compile: function(element, attrs) {
        element.append('<div ng-include="\'{{type}}-template.html\'"></div>');
        //or element.append('<div ng-include="\'{' + attrs.type + '}-template.html\'"></div>');
        //except the above won't interpret attr.type as a variable, just as the literal string 'item.type'
      }
  }
});

【问题讨论】:

  • 这里有一个有趣的articlecompile 以及它在Angularjs 中的工作原理。

标签: angularjs angularjs-directive angularjs-scope


【解决方案1】:

compile 函数没有scope 作为它的参数之一。

function compile(tElement, tAttrs, transclude) { ... }

注意:在最新版本的 Angular 中不推荐使用 transclude。

你有什么理由不想使用link

来自文档

compile 函数处理模板 DOM 的转换。由于大多数指令不进行模板转换,因此不经常使用。 compile 函数接受以下参数:

tElement - 模板元素 - 声明指令的元素。只对元素和子元素进行模板转换是安全的。

tAttrs - 模板属性 - 在所有指令编译函数之间共享的此元素上声明的规范化属性列表。

transclude - [已弃用!] 一个 transclude 链接函数:function(scope, cloneLinkingFn)

更新

要从compile 函数内部访问范围,您需要有preLinkpostLink 函数。在您的情况下,您只需要 postLink 函数。所以这...

compile: function compile(tElement, tAttrs, transclude) {
    return function postLink(scope, element, attrs) { ... }
},

建议的解决方案可能不准确,但应该对您有所帮助。

html

<div ng-app="myApp" ng-controller="app">
    <block type="item.type"></block>
</div>

JS(控制器+指令)

var myApp = angular.module('myApp', []);

myApp.controller('app', function ($scope, $http) {
    $scope.item = {
        type: 'someTmpl'
    };
}).directive('block', ['$compile', function ($compile) {
    return {
        restrict: 'AE',
        transclude: true,
        scope: {
            type: '='
        },
        compile: function (element, attrs) {
            return function (scope, element, attrs) {
                var tmpl;
                tmpl = scope.type + '-template.html';
                
                console.log(tmpl);
                
                element.append('<div ng-include=' + tmpl + '></div>');

                $compile(element.contents())(scope);
            };
        }
    };
}]);

【讨论】:

  • 嗯,我只是不知道如何使用链接-您的意思是在链接/监视功能中添加element.append('&lt;div ng-include="\''+value+'-template.html\'"&gt;&lt;/div&gt;'); 之类的东西吗?因为我试过了,一无所获……
  • @thatandrey,检查上面提出的解决方案;)
  • 嗨,谢谢,我想应该是console.log(tmpl)?我最终使用了element.append('&lt;div ng-include="\''+scope.type+'-template.html\'"&gt;&lt;/div&gt;');,因为我认为文件名周围应该有一组额外的括号,否则模板不会加载,否则,它会很好用,谢谢!
  • 最后一件事,我刚刚注意到,我想做的另一件事是访问范围模型中的其他属性,例如 item.content。在这里的小提琴中,我能够做到没有问题,但是类似的绑定似乎不适用于您的解决方案? jsfiddle.net/01h3ne4y 在那个小提琴中,我仍然可以从控制器访问foo.test
  • 如果您想访问整个项目对象,请将其绑定到类似 &lt;my-directive item=item&gt;&lt;/my-directive&gt; 的指令。 item 在您的控制器中成为 $scope.item,然后在您的指令中执行 scope: {item: '=item'}
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-10
  • 1970-01-01
  • 2020-07-28
  • 1970-01-01
相关资源
最近更新 更多