我有一个指令,其数据是通过api调用接收的。该指令本身工作正常,问题出现(我相信),因为该指令是在api调用完成之前加载的。这导致整个shebang不起作用。我得到{{user}}
。
我的指示如下:
app.directive('myDirective', function() {
return {
restrict: 'A',
require: '^ngModel',
scope: {
ngModel: '=',
},
template: '<tbody style="background-color: red;" ng-bind-html="renderHtml(listing_html)"></tbody>',
controller: ['$scope', '$http', '$sce',
function($scope, $http, $sce) {
$scope.listing_html += "<td>{{user.name}}</td>"
$scope.renderHtml = function(html_code) {
return $sce.trustAsHtml(html_code);
};
}
],
link: function(scope, iElement, iAttrs, ctrl) {
scope.$watch('ngModel', function(newVal) {
// This *is* firing after the data arrives, but even then the
// {{user}} object is populated. And the `user in ngModel` doesn't
// run correctly either.
console.log(scope.ngModel);
scope.listing_html = "<tr ng-repeat='user in ngModel'><td>{{user}}</td></tr>"
})
}
};
});
而我的HTML只是
<table my-directive my-options='{"Name": "name", "Email": "email"}' ng-model='userData'></table>
我已经创建了plunker,其中包含大量评论,希望有助于解释此问题。
此问题非常与this one类似,但该解决方案的关键区别不起作用。添加ng-cloak
只是让它不显示。
值得注意的是,我一直在使用this作为构建指令的方法的参考。
答案 0 :(得分:2)
我认为你要让它变得有点复杂。如果您要尝试在其中插入带有Angular表达式的动态HTML,则需要首先使用$ compile服务进行编译(这会将指令等挂接到动态HTML中,然后转换为Angular)。话虽如此,我认为你不需要为你想要完成的事情做到这一点。
看看这个更新的插件:http://plnkr.co/edit/RWcwIhlv3dMbjln4dOyb?p=preview
您可以使用指令中的模板生成所需的动态更改。在我的例子中,我使用ng-repeat来重复提供给指令的用户,以及提供给指令的选项。 ng-repeat进行观察,因此只要更新通过ng-model提供给指令的数据,ng-repeats就会反映这些变化。
<tbody style="background-color: red;">
<tr><th ng-repeat="option in myOptions">{{option.name}}</th></tr>
<tr ng-repeat="user in ngModel">
<td ng-repeat="option in myOptions">{{user[option.value]}}</td>
</tr>
</tbody>
我在主控制器中定义的选项如下。
$scope.tableOptions = [
{"name": "Name", "value": "name"},
{"name": "Email", "value": "email"}
];
您可以为指令使用添加其他属性,例如显示顺序等。您甚至可以动态地从选项中删除项目,然后从输出表中删除数据。
让我知道这是否有帮助,或者我是否误解了你想要完成的事情。
答案 1 :(得分:1)
我不是百分百肯定,但我相信ngBindHtml
在这种情况下不会帮助你
ngBindHtml
用于显示一些“普通”HTML,但您想要显示一些Angular,magic HTML
为此,您需要将$compile
HTML格式化为Angular-aware,并将link
已编译的HTML格式化为范围。
我使用了以下方法(结果非常好):
controller: function ($scope, $element, $compile) {
var html = createTmpl(angular.fromJson($scope.myOptions));
$scope.$watch('ngModel', function (newVal) {
var elem = angular.element(html); // Creating element
var linkingFn = $compile(elem); // Compiling element
linkingFn($scope); // Linking element
$element.html(''); // Removing previous content
$element.append(elem); // Inserting new content
// The above is purposedly explicit to highlight what is
// going on. It's moe concise equivalent would be:
//$element.html('').append($compile(html)($scope));
});
其中createTmpl()
被定义为考虑myOptions
并返回适当的模板以创建具有标题行(基于myOptions
的键)和数据行的表将属性定义为myOptions
的值:
function createTmpl(options) {
// Construct the header-row
var html = '<tr>';
angular.forEach(options, function (value, key) {
html += '<th>' + key + '</th>';
});
html += '</tr>\n';
// Construct the data-rows
html += '<tr ng-repeat="user in ngModel">';
angular.forEach(options, function (value, key) {
html += '<td>{{user' + value + '}}</td>';
});
html += '</tr>\n';
// Return the template
return html;
}
另请参阅此 short demo
<子>
当然,这仅用于演示目的,并不处理生产就绪应用程序应该处理的所有内容(例如,考虑错误,缺少属性,myOptions
和诸如此类的变化)。
子>
<强>更新强>:
我的竞争非常激烈,所以我对上面的代码做了一些修改,以支持嵌套属性。例如。给定具有以下结构的对象:
user = {
name: 'ExpertSystem',
company: {
name: 'ExpertSystem S.A.',
ranking: 100
}
};
我们可以将公司名称显示在表格的列中,只需定义myOptions
,如下所示:
myOptions='{"Company name": "company.name"}