ngRepeat 自定义指令标签
ngRepeat on custom directive tags
我有一个自定义指令列表,它们是我仪表板上的不同小部件。指令定义如下:
angular.module('core').directive('graphCardWidget', function() {
return {
restrict: 'E',
replace: true,
scope: {
target: '=target'
},
templateUrl: 'modules/core/widgets/graph-card.client.widget.html'
};
});
angular.module('core').directive('pieChartWidget', function() {
return {
restrict: 'E',
replace: true,
scope: {
target: '=target'
},
templateUrl: 'modules/core/widgets/pie-chart.client.widget.html'
};
});
在我的控制器中,我有一个要显示的小部件列表。名单如下:
$scope.dashboardWidgets = [
{
directive : 'graph-card-widget',
target : 'widgets.dashboards.activeDevicesCard'
},
{
directive : 'graph-card-widget',
target : 'widgets.dashboards.activeSessionsCard'
},
{
directive : 'pie-chart-widget',
target : 'widgets.dashboards.devices'
},
{
directive : 'pie-chart-widget',
target : 'widgets.dashboards.sessions'
}
];
现在在我看来,我使用ng-repeat
来迭代这个数组并显示项目。这是我的观点的代码:
<div layout="row" layout-wrap layout-align="center" layout-xs="column" ng-drop="true">
<div ng-repeat='widget in dashboardWidgets'>
<{{widget.directive}} ng-drag="true" flex='45' target='{{widget.target}}'>
</{{widget.directive}}>
<span flex='5'></span>
</div>
</div>
但是浏览器将其呈现为文本。这是我在 DOM:
中得到的
<div layout="row" layout-wrap="" layout-align="center" layout-xs="column" ng-drop="true" class="layout-wrap layout-xs-column layout-align-center-stretch layout-row">
<div ng-repeat="widget in dashboardWidgets" class="ng-binding ng-scope">
“<graph-card-widget ng-drag="true" flex='45' target='widgets.dashboards.activeDevicesCard’>”
<span flex="5" class="flex-5"></span>
</div>
<div ng-repeat="widget in dashboardWidgets" class="ng-binding ng-scope">
“<graph-card-widget ng-drag="true" flex='45' target='widgets.dashboards.activeSessionsCard’>”
<span flex="5" class="flex-5"></span>
</div>
<div ng-repeat="widget in dashboardWidgets" class="ng-binding ng-scope">
“<pie-chart-widget ng-drag="true" flex='45' target='widgets.dashboards.devices’>”
<span flex="5" class="flex-5"></span>
</div>
<div ng-repeat="widget in dashboardWidgets" class="ng-binding ng-scope">
“<pie-chart-widget ng-drag="true" flex='45' target='widgets.dashboards.sessions’>”
<span flex="5" class="flex-5"></span>
</div>
</div>
那么我该怎么做才能使指令呈现为标签而不是纯文本?
我看到了一些类似的问题,例如 question 1, question 2 但他们都在标准 HTML 标签中添加了动态指令。我需要的是动态标签。
更新:
按照@cnexans 的回答后,我让它部分工作了。小部件已绘制,但未评估 target
属性,这会导致出现空白小部件。
这是问题所在:https://plnkr.co/edit/BGN6C4LAHguWthU4fGy0?p=preview
不知道这是否符合您的要求。但我对你的阵列做了一些修改。
我使用 ng-bind-html
完成了此操作,当您绑定自定义元素(如指令)时,您需要再次编译它。为此,我创建(实际上是借用)了这个指令。
.directive('compileTemplate', function($compile, $parse){
return {
link: function(scope, element, attr){
var parsed = $parse(attr.ngBindHtml);
function getStringValue() { return (parsed(scope) || '').toString(); }
//Recompile if the template changes
scope.$watch(getStringValue, function() {
$compile(element, null, -9999)(scope); //The -9999 makes it skip directives so that we do not recompile ourselves
});
}
}
});
我把 ng-repeat
改成了这样
<div ng-repeat='widget in dashboardWidgets' compile-template ng-bind-html="trust(widget.directive)">
<span flex='5'></span>
</div>
信任函数将 return 信任 html
$scope.trust = function(someHTML){
return $sce.trustAsHtml(someHTML);
}
像这样修改数组
$scope.dashboardWidgets = [
{
directive : '<graph-card-widget ng-drag="true" flex="45" target="widget.target"></ graph-card-widget>',
target : 'widgets.dashboards.activeDevicesCard'
},
{
directive : '<graph-card-widget ng-drag="true" flex="45" target="widget.target"></ graph-card-widget>',
target : 'widgets.dashboards.activeSessionsCard'
},
{
directive : '<pie-chart-widget ng-drag="true" flex="45" target="widget.target"></ pie-chart-widget>',
target : 'widgets.dashboards.devices'
},
{
directive : '<pie-chart-widget ng-drag="true" flex="45" target="widget.target"></ pie-chart-widget>',
target : 'widgets.dashboards.sessions'
}
];
您可以在 ng-for 中使用 ng-if 以便在每次迭代中切换名称 "directive" 以显示一个或另一个指令。
<div ng-repeat="data in dashboardWidgets">
<div ng-if="data.directive == 'graph-card-widget'">
<graph-card-widget ng-drag="true" flex='45' target=data.target>
</graph-card-widget>
<span flex='5'></span>
</div>
<div ng-if="data.directive == 'pie-chart-widget'">
<pie-chart-widget ng-drag="true" flex='45' target=data.target>
</pie-chart-widget>
<span flex='5'></span>
</div>
</div>
您也可以创建一个容器指令来处理此逻辑,这样您就可以在需要时将此功能共享给其他页面。
<widgets-container widgets-list=data></widgets-container>
工作示例:https://codepen.io/anon/pen/jBzEpe?editors=1010#0
编辑:
检查你给出的例子,你需要传递一个Widget对象给指令,而你传递的是一个字符串。这是一个从 plunkr given
分叉出来的工作示例
https://plnkr.co/edit/3Oxxmp?p=preview
它有一个函数 namespaceToObject,可以将字符串从 $scope 转换为所需的对象。
我有一个自定义指令列表,它们是我仪表板上的不同小部件。指令定义如下:
angular.module('core').directive('graphCardWidget', function() {
return {
restrict: 'E',
replace: true,
scope: {
target: '=target'
},
templateUrl: 'modules/core/widgets/graph-card.client.widget.html'
};
});
angular.module('core').directive('pieChartWidget', function() {
return {
restrict: 'E',
replace: true,
scope: {
target: '=target'
},
templateUrl: 'modules/core/widgets/pie-chart.client.widget.html'
};
});
在我的控制器中,我有一个要显示的小部件列表。名单如下:
$scope.dashboardWidgets = [
{
directive : 'graph-card-widget',
target : 'widgets.dashboards.activeDevicesCard'
},
{
directive : 'graph-card-widget',
target : 'widgets.dashboards.activeSessionsCard'
},
{
directive : 'pie-chart-widget',
target : 'widgets.dashboards.devices'
},
{
directive : 'pie-chart-widget',
target : 'widgets.dashboards.sessions'
}
];
现在在我看来,我使用ng-repeat
来迭代这个数组并显示项目。这是我的观点的代码:
<div layout="row" layout-wrap layout-align="center" layout-xs="column" ng-drop="true">
<div ng-repeat='widget in dashboardWidgets'>
<{{widget.directive}} ng-drag="true" flex='45' target='{{widget.target}}'>
</{{widget.directive}}>
<span flex='5'></span>
</div>
</div>
但是浏览器将其呈现为文本。这是我在 DOM:
中得到的<div layout="row" layout-wrap="" layout-align="center" layout-xs="column" ng-drop="true" class="layout-wrap layout-xs-column layout-align-center-stretch layout-row">
<div ng-repeat="widget in dashboardWidgets" class="ng-binding ng-scope">
“<graph-card-widget ng-drag="true" flex='45' target='widgets.dashboards.activeDevicesCard’>”
<span flex="5" class="flex-5"></span>
</div>
<div ng-repeat="widget in dashboardWidgets" class="ng-binding ng-scope">
“<graph-card-widget ng-drag="true" flex='45' target='widgets.dashboards.activeSessionsCard’>”
<span flex="5" class="flex-5"></span>
</div>
<div ng-repeat="widget in dashboardWidgets" class="ng-binding ng-scope">
“<pie-chart-widget ng-drag="true" flex='45' target='widgets.dashboards.devices’>”
<span flex="5" class="flex-5"></span>
</div>
<div ng-repeat="widget in dashboardWidgets" class="ng-binding ng-scope">
“<pie-chart-widget ng-drag="true" flex='45' target='widgets.dashboards.sessions’>”
<span flex="5" class="flex-5"></span>
</div>
</div>
那么我该怎么做才能使指令呈现为标签而不是纯文本?
我看到了一些类似的问题,例如 question 1, question 2 但他们都在标准 HTML 标签中添加了动态指令。我需要的是动态标签。
更新:
按照@cnexans 的回答后,我让它部分工作了。小部件已绘制,但未评估 target
属性,这会导致出现空白小部件。
这是问题所在:https://plnkr.co/edit/BGN6C4LAHguWthU4fGy0?p=preview
不知道这是否符合您的要求。但我对你的阵列做了一些修改。
我使用 ng-bind-html
完成了此操作,当您绑定自定义元素(如指令)时,您需要再次编译它。为此,我创建(实际上是借用)了这个指令。
.directive('compileTemplate', function($compile, $parse){
return {
link: function(scope, element, attr){
var parsed = $parse(attr.ngBindHtml);
function getStringValue() { return (parsed(scope) || '').toString(); }
//Recompile if the template changes
scope.$watch(getStringValue, function() {
$compile(element, null, -9999)(scope); //The -9999 makes it skip directives so that we do not recompile ourselves
});
}
}
});
我把 ng-repeat
改成了这样
<div ng-repeat='widget in dashboardWidgets' compile-template ng-bind-html="trust(widget.directive)">
<span flex='5'></span>
</div>
信任函数将 return 信任 html
$scope.trust = function(someHTML){
return $sce.trustAsHtml(someHTML);
}
像这样修改数组
$scope.dashboardWidgets = [
{
directive : '<graph-card-widget ng-drag="true" flex="45" target="widget.target"></ graph-card-widget>',
target : 'widgets.dashboards.activeDevicesCard'
},
{
directive : '<graph-card-widget ng-drag="true" flex="45" target="widget.target"></ graph-card-widget>',
target : 'widgets.dashboards.activeSessionsCard'
},
{
directive : '<pie-chart-widget ng-drag="true" flex="45" target="widget.target"></ pie-chart-widget>',
target : 'widgets.dashboards.devices'
},
{
directive : '<pie-chart-widget ng-drag="true" flex="45" target="widget.target"></ pie-chart-widget>',
target : 'widgets.dashboards.sessions'
}
];
您可以在 ng-for 中使用 ng-if 以便在每次迭代中切换名称 "directive" 以显示一个或另一个指令。
<div ng-repeat="data in dashboardWidgets">
<div ng-if="data.directive == 'graph-card-widget'">
<graph-card-widget ng-drag="true" flex='45' target=data.target>
</graph-card-widget>
<span flex='5'></span>
</div>
<div ng-if="data.directive == 'pie-chart-widget'">
<pie-chart-widget ng-drag="true" flex='45' target=data.target>
</pie-chart-widget>
<span flex='5'></span>
</div>
</div>
您也可以创建一个容器指令来处理此逻辑,这样您就可以在需要时将此功能共享给其他页面。
<widgets-container widgets-list=data></widgets-container>
工作示例:https://codepen.io/anon/pen/jBzEpe?editors=1010#0
编辑:
检查你给出的例子,你需要传递一个Widget对象给指令,而你传递的是一个字符串。这是一个从 plunkr given
分叉出来的工作示例https://plnkr.co/edit/3Oxxmp?p=preview
它有一个函数 namespaceToObject,可以将字符串从 $scope 转换为所需的对象。