我正在开发一个AngularJS Data Table指令(仍为WIP)的开源项目。当您查看Angular Grid或UI Grid等组件时,它们都会在父控制器的对象中描述它们的列和属性,如:
$scope.gridOptions = {
enableSorting: true,
enableCellEditOnFocus: true,
columnDefs: [
{ name: 'field1', enableSorting: false, enableCellEdit: false },
{ name: 'field2' },
{ name: 'field3', visible: false }
]
};
工作正常但是,我认为这不是真正的“角度方式”。感觉更像是一个jQuery小部件。如果你看一下像Angular Material这样的项目,它们在HTML模板和对象驱动中更具表现力。
对于我的实现,我最初想要使它非常富有表现力并暴露我使用的每个内部指令,然而,最终只是创建一个基本表。所以我对其他框架进行了一些研究,发现react有一个很好的架构,你可以在其中定义如下列:
React.render(
<Table
rowHeight={50}
rowGetter={rowGetter}
rowsCount={rows.length}
width={5000}
height={5000}
headerHeight={50}>
<Column
label="Col 1"
width={3000}
dataKey={0}
/>
<Column
label="Col 2"
width={2000}
dataKey={1}
/>
</Table>,
document.getElementById('example')
);
我爱上了这种方法,它既简单又富有表现力。 90%的情况下,您只想自定义列模板。所以不要这样:
$scope.gridOptions = {
enableFiltering: true,
rowTemplate: rowTemplate(),
data: 'data',
columnDefs: [
{ name: 'name' },
{ name: 'gender' },
{ name: 'company' },
{ name: 'widgets' },
{
name: 'cumulativeWidgets',
field: 'widgets',
cellTemplate: '<div class="ui-grid-cell-contents" title="TOOLTIP">{{grid.appScope.cumulative(grid, row)}}</div>'
}
]
};
使用单元格模板,您可以执行以下操作:
<dt options="options" rows="data" class="material">
<Column name="name" width="300"></Column>
<Column name="Gender">
<strong>{{value}}</strong>
</Column>
<Column name="Company"></Column>
</dt>
注意我如何使用React概念并将其与更具角度的概念配对,其中我将包括在列中具有模板的能力。
现在好了,问题。我希望init上的列,但不是之后。我想用实际的表替换它。问题是当我需要它时,我永远无法获得HTML。
所以on this line我尝试做类似的事情:
compile: function(tElem, tAttrs){
var tags = z.getElementsByTagName('column');
console.log(tags) // equals = []
return {
pre: function($scope, $elm, $attrs, ctrl){
}
};
}
但是当我试图将它们转移时,这些列永远不会存在(不是我想做的事情)。在控制器初始化之前,我需要一种方法来获取它们,模板将替换内部内容。这是一个plunkr!
此外,由于我的指令是作用域的(我因为性能原因我想做的)我无法访问父作用域以使用外部内容编译内部模板。
此外,有关此设计范例的任何建议/想法吗?谢谢!
答案 0 :(得分:3)
Try to use the template
as a function, which returns the actual template string. The first parameter is the original html:
var tags;
return {
template: function(element) {
tags = element[0].getElementsByTagName('column');
return "<div>table</div>"
},
compile: ...
}
答案 1 :(得分:1)
我只找到了一种奇怪的方式来实现你想要的东西。
在有人提供更好的解决方案之前,我的工作是plunker。
将$transclude
服务添加到控制器并将transclude:'element'
添加到指令
app.directive("simple", function(){
return {
restrict: "EA",
replace:true,
transclude:'element',
template:"<div>table</div>",
compile: function(element, attributes, transclude){
var tags = element[0].getElementsByTagName('column');
console.log("compile", tags);
console.log("transclude", transclude);
return {
pre: function(scope, element, attributes, controller, transcludeFn){
var tags = element[0].getElementsByTagName('column');
console.log("pre", tags);
},
post: function(scope, element, attributes, controller, transcludeFn){
var tags = element[0].getElementsByTagName('column');
console.log("post", tags);
}
}
},
controller: function($scope, $element, $transclude){
$transclude(function(clone,scope){
/* for demo am converting to html string*/
console.log("From controller",angular.element(clone).find('column'));
});
}
};
});
我测试了其他一些东西。但我只能使用此列并且只能进入控制器。