我找到了解决方案!
首先,我使用了 AngularJS 网站主页上的最后一个示例:
http://angular.github.io/angularjs.org/#/list
这很好开始,但渲染的 HTML 代码总是包含一些垃圾,因为我不得不这样做使用 ng-transclude 指令来<FIELD>
处理元素。
因此,我进一步查看并找到了一些动态创建模板的示例。这提供了更大的灵活性,我可以完全重写 HTML,而不会在结果代码中出现任何旧的片段。
我还必须使用不同的方法在指令之间进行通信,因为当主指令的模板中没有使用 ng-transclude 时,AngularJS 网站(共享控制器)中使用的方法会失效。我只对模块对象使用了一个附加属性,因为两个指令都属于同一个对象。
这是解决方案的完整代码。我希望它对某些人有用。
HTML:
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body ng-app="flexlist">
<array title="Breakdown" data="record">
<field type="text" default="" name="descr" title="Description"></field>
<field type="number" default="0" name="price" title="Price"></field>
<field type="number" default="0" name="tax" title="Tax"></field>
</array>
<array title="test" data="record">
<field type="text" default="" name="descr" title="Description"></field>
</array>
</body>
<script src="js/angular.js"></SCRIPT>
<script src="js/controller.js"></SCRIPT>
</html>
带有大量注释的 Javascript ;-)
function record(){ //a simple constructor to provide the data for the table
return [{
descr: "example",
price: 10,
tax: 0.07
},
{
descr: "something else",
price: 15,
tax: 0.11
}
];
}
var mod=angular.module('flexlist', []);
mod.fields=[]; //container that is shared between directives
//the directive for <ARRAY>
mod.directive('array', function($compile){ //injecting the $compile service
return {
restrict: 'E', //restricted to element only
replace: true,
scope:{
title: '@title' //getting the title attribute into the scope
},
link: function(scope,element,attr){
//calling the function specified in the "data" attribute
//which should return the data to be filled into the table
scope.source=window[attr.data]();
scope.fields=[]; //preparing the "field" variable in the scope
//copying the data collected from the <field> elements into the scope
angular.copy(mod.fields,scope.fields);
//preparing the collection for the next use
//(in case more than one <ARRAY> block is in a page
mod.fields=[];
newCont=angular.element( //creating the template's HTML
'<FIELDSET>'+
'<LEGEND>{{title}}</LEGEND>'+
'<TABLE border=1>'+
'<TR>'+
'<TH ng-repeat="fld in fields">{{fld.title}}</TH>'+
'</TR>'+
'<TR ng-repeat="line in source">'+
'<TD ng-repeat="fld in fields">{{line[fld.name]}}</TD>'+
'</TR>'+
'</TABLE>'+
'</FIELDSET>');
//applying the Angular "magic" -- the directives in the template
$compile(newCont)(scope);
element.replaceWith(newCont); //replace the whole <ARRAY> element
},
controller: function($scope, $attrs){
// nothing here yet
}
};
});
mod.directive('field',function(){
return {
require: '^array', //the "^" means that <FIELD> has to be inside <ARRAY>
restrict: 'E', //restricted to be an element only
link: function(scope,element,attrs){ //collecting the data from the element
mod.fields.push({ //pushing the data into the collection object
type: attrs.type,
'default': attrs['default'],
name: attrs.name,
title: attrs.title
});
}
};
});