我正在尝试创建一个通用指令,我想用它来显示一个灵活的,类似电子表格的数据输入表单。
我想把所有数据结构放在一起。格式化html代码中的信息并让指令将其存储在范围内以供以后使用。
以下是我想要使用的示例HTML("字段"元素中的信息是我想要进入的范围):
<array title="Breakdown" data="data.breakdown">
<field type="text" default="" name="descr">Description</field>
<field type="number" default="0" name="price">Price</field>
<field type="number" default="0" name="tax">Tax</field>
</array>
到目前为止的指令
.directive('array', function(){
return {
restrict: "E",
replace: true,
transclude: true,
templateUrl: "js/array-template.html",
compile: function(tElement, tAttrs, transclude) {
var x=transclude(tElement);
return function(scope, element, attrs) { //the linking function
scope.title=attrs.title;
}
}
}
}
变量x给了我一个html元素数组,但它不仅包含&#34;字段&#34;元素,但一堆空&#34; span&#34;元素也是。如果需要,我可以使用它,但我怀疑这是一种更简单的方法。
答案 0 :(得分:0)
我找到了解决方案!
首先,我使用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
});
}
};
});