我正在设计一个显示面板列表的界面,每个面板都有自己的模型。我希望能够使用父控制器中的模型渲染每个面板,使其具有自己的模型。
类似的东西:
function Parent() {
this.panels = [{name: "Foo", place: "Bar"}, {name: "Hello", place: "World"}];
}
function Child(model) {
var model = model //{name: "Foo", place: "Bar"}
}
for (var i = 0; i < Parent.panels.length; i++) {
new Child(Parent.panels[0]);
}
我的问题是:在“有棱有角的心态”中,解决这个问题的最佳方法是什么?
我目前的计划如下。我将有两个控制器,一个用于面板列表,一个用于每个单独的面板。所以,像这样:
angular.module("panelApp", [])
.service("panelService", function() {
var panels = [/* panel classes */];
return {
getPanels: function() { return panels }
}
})
.controller("PanelListCtrl", ["$scope", "panelService", function($scope, panelService) {
$scope.panels = panelService.getPanels();
$scope.currentPanel = $scope.panels[0];
})
.controller("PanelCtrl", ["$scope", "panelService", function($scope, panelService) {
//this is where stuff gets hazy
for (var i = 0; i < PanelListCtrl.panels.length; i++) {
//generate child panels... somehow... =(
}
})
我显然没有做到这一点,但总体思路是我希望能够为列表和每个单独的面板封装功能。
我提出的另一种方法是使用指令:
angular.module("panelApp", [])
.service("panelService", function() {
var panels = [/* panel classes */];
return {
getPanels: function() { return panels }
}
})
.controller("PanelListCtrl", ["$scope", "panelService", function($scope, panelService) {
$scope.panels = panelService.getPanels();
$scope.currentPanel = $scope.panels[0];
})
.directive("panel", function() {
require:"PanelListCtrl",
restrict: "E",
link: function(scope, element, attrs, panelListCtrl) {
for (var i = 0; i < panelListCtrl.panels.length; i++) {
//generate markup... somehow. How can one create directive markup in the DOM on the fly??
}
},
templateUrl: "template.html"
})
我现在已经对抗这个黑白花了一个小时了。请帮忙。
备注
我忘了提到的是,显示的面板数量是可变的。因此,在加载页面时,DOM中没有标记,必须动态注入。我是角色的新手,我不知道如何根据框架使用的MV *方法动态地向页面添加元素。
答案 0 :(得分:1)
这应该让你开始:http://plnkr.co/edit/b7KbXMPWOhAG50ajYyYN?p=preview
您的基本想法是合理的,使用分层范围,它可以使用控制器中的范围继承以及控制器和指令之间的实现。因为我怀疑你需要的主要是UI,所以你最好定义一个指令。
此外,在动态生成模板时,您可能需要的是一个静态模板,用于填充所需值的面板。然后,您可以使用ng-repeat
生成其中的许多内容。
<强>控制器强>
.controller("PanelListCtrl", ["$scope", "panelService", function($scope, panelService) {
$scope.panels = panelService.getPanels();
// Saving the `isActive` property in the model, keeping the controller thin.
$scope.panels[0].isActive = true;
// This will manage the selection of the correct panel.
$scope.selectPanel = function (panel) {
$scope.panels.forEach(function (p) {
p.isActive = p === panel;
});
};
}])
.directive("panel", function() {
return {
restrict: "A",
link: function(scope, element, attrs) {
scope.$watch(attrs.panel, function (newVal) {
scope.panel = newVal; // <-- watch and populate the `panel` in the current scope.
// The directive cam be made to
// work even without this link function (because of scope
// inheritence) but the best-practise is to keep the directives
// as loosely coupled with the controller as possible.
// In this case, you'll be free the name the panel variable anything
// in the controller as long
// as you pass the variable to the directive: <div panel="nameOfPanel"></div>
})
},
templateUrl: "panel.html" // <-- template is here for One of the panes.
}
})
<强>模板强>
<body ng-controller="PanelListCtrl">
<div ng-repeat="p in panels">
<button ng-click="selectPanel(p)">Select panel {{$index}}</button>
<div panel="p"></div>
</div>
</body>