我是AngularJS的新手,希望有人可以帮助我!
我正在开发一个Widget容器,它允许向容器添加新的预定义小部件。 每个小部件都有自己的行为,因此每个小部件类型需要一个控制器。 窗口小部件可以是ChartBar或DataTable,因此其控制器必须知道如何使用数据填充窗口小部件,这就是我为每种窗口小部件类型使用控制器的原因。
我做了什么: 我可以向容器中添加新的小部件,但只有在我点击"添加小部件2"时才添加一种类型的小部件。和"添加小工具3"的按钮。
请参阅Plunkr了解演示。
也许我的方法如何实现这一点是完全错误的。在这种情况下,将非常感谢指导。
我的HTML:
<div class="col-lg-12">
<button class="btn btn-xs btn-success" ng-click="addWidget(1)">Add Widget 1</button>
<button class="btn btn-xs btn-success" ng-click="addWidget(2)">Add Widget 2</button>
<button class="btn btn-xs btn-success" ng-click="addWidget(3)">Add Widget 3</button>
</div>
<div class="portlets-wrapper">
<!-- START row-->
<div class="row">
<widget-container id="portlet-1" portlet="portlet" container="widgetList" class="col-lg-4"></widget-container>
</div>
<!-- END row-->
</div>
</div>
我的widget-container指令:
angular.module('myApp').directive('widgetContainer', function ($rootScope, $compile) {
var controller = 'Widget1Controller';
var linker = function(scope, element, attrs) {
scope.$watch('ctrl.container', function(newValue, oldValue) {
if(newValue.length>0){
var item = newValue[newValue.length-1];
var widgetId = Math.floor((Math.random() * 100) + 1);
if(item.type ==1) controller= 'Widget1Controller';
if(item.type ==2) controller= 'Widget2Controller';
if(item.type ==3) controller= 'Widget3Controller';
element.html(element.html() + getTemplate(scope, item.type)).show();
$compile(element.contents())(scope);
}
}, true);
};
var getTemplate = function(scope, type) {
var template1 = '<div id="panelPortlet" class="panel panel-default">\
<div class="panel-heading portlet-handler">{{ widgetName || "Another Widget"}} \
<paneltool tool-collapse="tool-collapse" tool-dismiss="tool-dismiss" tool-refresh="traditional" tool-settings="tool-settings"></paneltool>\
</div>\
<div collapse="panelPortlet" class="panel-wrapper">\
<div class="panel-body">\
Another Widget {{ getData() }}\
</div>\
</div>\
</div>';
var template2 = '<div id="panelPortlet" class="panel panel-default">\
<div class="panel-heading portlet-handler">{{ widgetName || "Chart Bar"}} \
<paneltool tool-collapse="tool-collapse" tool-dismiss="tool-dismiss" tool-refresh="traditional" tool-settings="tool-settings"></paneltool>\
</div>\
<div collapse="panelPortlet" class="panel-wrapper">\
<div class="panel-body">\
ChartBar {{ getData() }}\
</div>\
</div>\
</div>';
var template3 = '<div id="panelPortlet" class="panel panel-default">\
<div class="panel-heading portlet-handler">{{ widgetName || "Line Chart"}} \
<paneltool tool-collapse="tool-collapse" tool-dismiss="tool-dismiss" tool-refresh="traditional" tool-settings="tool-settings"></paneltool>\
</div>\
<div collapse="panelPortlet" class="panel-wrapper">\
<div class="panel-body">\
LineChart {{ getData() }}\
</div>\
</div>\
</div>';
if(type==1) return template1;
if(type==2) return template2;
if(type==3) return template3;
};
return {
restrict: "E",
link: linker,
scope: {
container:'='
}
,controller: controller
,bindToController: true
,controllerAs: 'ctrl'
};
});
答案 0 :(得分:3)
我认为一种正确的方法是将每个html模板划分为不同的模板文件。在此之后,我将创建一个widget-container指令和一个widget指令,它需要使用widget-container指令(require: '^widget-container'
)。
html可能有这样的东西:
<widget-container>
<widget ng-repeat="widget in widgetList"></widget>
</widget-container>
widget-container指令应该管理widgetList对象,作为其范围的一部分。
现在,在您的widget指令中,您可以定义一个模板,使用ng-switch
管理多个模板。保持代码清洁和可重用是很重要的,因此如果窗口小部件的行为完全不同,您应该考虑为每个窗口小部件定义不同的指令。
在这种情况下可能是这样的:
<widget-container>
<div ng-repeat="widget in widgetList">
<div ng-switch="{{ widget.type }}">
<widget1 ng-switch-when="1" />
<widget2 ng-switch-when="2" />
</div>
</div>
</widget-container>
修改强>
所以在这里,带有示例的plunker工作得很好。我真的相信它是一个更清晰的代码,永远记住angularjs可以帮助你保持代码的可重用性和高度可维护性。
http://plnkr.co/edit/uYRsGDUutMDKsbpmchNK
我已将您的脚本分为3个不同的指令:widgetA,widgetB和widgetC。他们三个都有自己的模板(template1,template2和template3)。
利用javascript设计模式,我还为每个小部件创建了构造函数。函数addWidget(widgetType)
定义了应该调用哪个构造函数。
$scope.addWidget = function(widgetType) {
var newWidget = null;
switch (widgetType) {
case 1:
newWidget = new WidgetA();
break;
case 2:
newWidget = new WidgetB();
break;
case 3:
newWidget = new WidgetC();
break;
}
$scope.widgetList.push(newWidget);
};
function WidgetA() {
this.type = 1;
this.widgetName = 'I`m a widget 1';
this.getData = function() {
return [1, 1, 1, 1, 1, 2, 3, 4, 5];
};
}
function WidgetB() {
this.type = 2;
this.widgetName = 'I`m a widget 2';
this.getData = function() {
return [1, 2, 2, 2, 2, 2, 3, 4, 5];
};
}
function WidgetC() {
this.type = 3;
this.widgetName = 'I`m a widget 3';
this.getData = function() {
return [1, 2, 3, 3, 3, 3, 4, 5];
};
}
在这种情况下,widgetContainer指令不是必需的。
看一看, 希望它有所帮助!