AngularJS : 以编程方式重用自定义指令

AngularJS : Reuse custom directive programmatically

我正在处理我的第一个单页 Angular.js 应用程序,我有点卡在以编程方式 compilling/evaluating 自定义指令,以便从控制器中将其插入 DOM .我创建的自定义指令使用两个值(return 函数并接受一个参数)和一个参数。整个事情在 SPA 的初始 html 中与 ng-repeat 一起工作正常:

.directive('myDirective', ['value1', 'value2', function('value1', 'value2'){
    return {
        restrict: 'E',
        scope: {
            param: '=param'
        },
        replace: true,
        templateUrl: '/path/to/template.html',
        link: function(scope, element, attrs){
            scope.v1 = value1(scope.param);
            scope.v2 = value2(scope.param);
        }
    };
})

指令模板看起来有点像这样:

<div>
    <img ng-src="{{ param.img.src }}" />
    <div>
        <a href="{{ param.link.src }}">{{ param.link.text }}</a>
        <time datetime="{{ v1 }}">{{ v2 | date: 'medium' }}</time>
        <span ng-bind-html="param.text | customFilter1 | customFilter2 | customFilter3"></span>
    </div>
</div>

当我像这样在页面 html 中使用此指令时,一切正常:

<ul ng-controller="SomeController" ng-cloak>
    <li ng-repeat="param in params">
        <my-directive param="param"></my-directive>
    </li>
</ul>

我现在想重用该指令,以在控制器内的函数中以编程方式动态生成相应的 html。 我的方法是尝试使用 $compile 函数但没有成功:

// in controller:
// ...
$scope.generateMyDirective = function(param){
    var compiled = $compile('<my-directive param="param"></my-directive>')({});
    someElement.innerHTML = compiled[0];
};

结果(即 someElement)确实包含指令的静态 html,但不会计算指令中的任何表达式,例如{{ param.img.src }}{{ v1 }}。此外抛出以下类型错误:

TypeError: scope.$new is not a function

我尝试使用不同的范围进行编译,例如$scope 控制器或简单地 true 生成一个新的范围,但 none 将计算指令模板中的表达式。我还尝试在将指令 html 插入 someElement 后调用 $scope.$apply(),但也没有用。

我有点卡在这一点上,没有想法,感谢任何提示。我希望你们能帮我解决这个问题。

您犯错的第一件事是您的指令不正确。驼峰式大小写应 - 与所有小写字母分开

应该是

<my-directive param="param"></my-directive>

而不是

<myDirective param="param"></myDirective>

此外 $compile 应该使用作用域编译元素,你不必担心从控制器创建新的 scope,你的指令已经有一个独立的作用域。

$compile('<my-directive param="param"></my-directive>')($scope);
  1. 您应该为指令编译器提供任何范围
  2. 所有使用的变量(见下文 p)应该在提供的范围内可解析

$scope.p = {img: '', ...};  
$compile('<my-directive param="p"></my-directive>')($scope);
delete $scope.p;

我在@vp_rath 和@pankajparkar 的帮助下解决了这个问题! 问题确实在于$scope。为了将 param 传递给对 $compile() 的调用,我们有两种可能的选择。一种解决方案是将 param 绑定到控制器的范围并添加一个 $watch()。这样做的第二种方法(以及我正在寻找的更多方法)是:与其绑定到控制器的 $scope,不如像这样创建一个新的普通作用域:

// controller:
//
var generateMyDirection = function(param){
    var scope = $rootScope.$new();
    scope.param = param;
    var compiled = $compile('<my-directive param="param"></my-directive>')(scope);
    someElement.innerHTML = compiled[0];
};