简体   繁体   English

AngularJS:编译指令的输出

[英]AngularJS: Compiling the output of a directive

i have some kind of legacy angularjs code which creates a dynamic table using a directive where the controller can overwrite the behavior of the table (on how to display the data) 我有某种传统的angularjs代码,它使用指令创建动态表,在该指令中控制器可以覆盖表的行为(关于如何显示数据)

It consists of the following setup (simplified): 它由以下设置(简化)组成:

Directive's controller 指令的控制器

.directive('datatable', [function () {
    return {
        scope: {
            items: '=',
            tablemetadata: '=',
            processors: '=?'
        },
        controller: ...
        $scope.processField = function processField(item, data){
        if($scope.processors === undefined){return;}
            for(var i = 0; i < $scope.processors.length; i++){
                if($scope.processors[i].field===field){
                    var newData = $scope.processors[i].processor(item, data);
                    return $sce.trustAsHtml(newData);
                }
            }
            return data;
        };
    ...

Directive's Template 指令的模板

<tr ng-repeat="item in items">
    <td ng-repeat="column in tableMetadata.columns" ng-bind-html="processField(column.field, $eval('item.'+column.field))"></td>
</tr>

Controller 控制者

$scope.myItems = [{id: 2, otherProperty: "text"}];

$scope.tableMetadata = {
    columns: [
        {field: 'id', headerKey: 'object id'},
        {field: 'otherProperty', headerKey: 'some data'},
    ]
};

$scope.tableProcessors = [
    {field: 'id', processor: function(entry, data){ //data = content of object.id
        var retVal = "<a ng-click='alert(" + data + ");'>click me</a>";
        return retVal;
    }}
];

Controller's view 管制员的观点

<datatable items="myItems" tablemetadata="tableMetadata" processors="tableProcessors"></datatable>

I need to generate buttons (or other html-elements) for some specific properties, like a link (like shown above). 我需要为某些特定属性生成按钮(或其他html元素),例如链接(如上所示)。

The Button is displayed but the ng-click handler is not working. 显示按钮,但是ng-click处理程序不起作用。 This makes sense since it wasn't compiled to the scope. 这是有道理的,因为它没有编译到范围内。

How do I correctly compile the new element and add it to the table? 如何正确编译新元素并将其添加到表中?

A simple solution can be to not use an isolated scope. 一个简单的解决方案可以是不使用隔离范围。 Change your scope from scope: { ... } to scope: true and use $scope.$eval to evaluate your attributes. 将范围从范围:{...}更改为范围:true,然后使用$ scope。$ eval评估属性。

Another solution (most elegant) can be to use angularjs transclusion (see here ). 另一个解决方案(最优雅)可以是使用angularjs包含(请参阅此处 )。 But this solution ask to modify your dom representation of your directive. 但是此解决方案要求修改您的指令的dom表示形式。

In your link method in the directive you have to use 在指令的link方法中,您必须使用

elem.append( $compile(html)(scope) );

As for separating the concerns cleanly, I would make each <td> its own directive that inherits what you are currently concatenating as a string in its isolated scope properties. 至于清楚地分离问题,我将使每个<td>都有自己的指令,该指令继承您当前作为其隔离范围属性中的字符串连接的内容。 Instead of 代替

var retVal = "<a ng-click='alert(" + data + ");'>click me</a>";

<tr ng-repeat="item in items">
    <td ng-repeat="column in tableMetadata.columns" ng-bind-html="processField(column.field, $eval('item.'+column.field))"></td>
</tr>

use something like: 使用类似:

<tr ng-repeat="item in items">
  <table-item ng-repeat="..." process-field="item"></table-item>
</tr>

/** directive compiles dynamically */

scope: {
  processField: '='
},
link: function(scope, elem, attr, ctrl) {
  var template = `<a ng-click="${ctrl.processField}"></a>`;
  elem.append( $compile(template)(scope) );
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM