使用AngularJS生成动态内容

时间:2015-10-07 15:34:05

标签: angularjs angularjs-directive

我是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'
    };
});

1 个答案:

答案 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指令不是必需的。

看一看, 希望它有所帮助!