【问题标题】:AngularJS: Compiling the output of a directiveAngularJS:编译指令的输出
【发布时间】:2016-05-03 12:49:28
【问题描述】:

我有一些遗留的 angularjs 代码,它使用一个指令创建一个动态表,控制器可以覆盖表的行为(关于如何显示数据)

它由以下设置(简化)组成:

指令的控制器

.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;
        };
    ...

指令的模板

<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>

控制器

$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;
    }}
];

控制器视图

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

我需要为某些特定属性生成按钮(或其他 html 元素),例如链接(如上所示)。

显示按钮,但 ng-click 处理程序不起作用。这是有道理的,因为它没有被编译到作用域中。

如何正确编译新元素并将其添加到表格中?

【问题讨论】:

    标签: javascript angularjs compilation


    【解决方案1】:

    在你必须使用的指令中的link 方法中

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

    至于干净地分离关注点,我会让每个&lt;td&gt; 都有自己的指令,该指令继承您当前在其隔离范围属性中作为字符串连接的内容。而不是

    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>
    

    使用类似的东西:

    <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) );
    }
    

    【讨论】:

      【解决方案2】:

      一个简单的解决方案是不使用隔离范围。 将您的范围从 scope: { ... } 更改为 scope: true 并使用 $scope.$eval 来评估您的属性。

      另一种解决方案(最优雅的)是使用 angularjs 嵌入(参见here)。但是这个解决方案要求修改你的指令的 dom 表示。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-02-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-26
        • 2014-11-15
        相关资源
        最近更新 更多