2015-10-07 181 views
0

我是AngularJS的新手,希望有人能幫助我!使用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> 

我的窗口小部件容器指令:

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

回答

3

我認爲,正確的方法是在不同的模板來劃分文件的每個HTML模板。在此之後,我將創建一個widget-container指令和一個widget指令,它要求使用widget-container指令(require: '^widget-container')。

的HTML可能有這樣的事情:

<widget-container> 
     <widget ng-repeat="widget in widgetList"></widget> 
</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指令是不必要的。

看看吧, 希望它有幫助!

+0

這是一個不錯的方法!現在,使用具有multiples指令的ng-switch應該怎麼做widget-container指令?你能提供一個更詳細的例子或plunkr嗎? – Hernan

+0

等等?它有幫助嗎? –

+0

謝謝你!現在更清楚了。使用這種方法我正面臨另一個問題。所使用的數據陣列只是一個示例,我需要從API中提取數據,以便在添加新小部件時重繪所有小部件,以便爲每個小部件進行API調用。我認爲,在每個widgetList推動中防止小部件重繪應該修復它,但我不知道該怎麼做。思考? – Hernan