2017-07-05 29 views
0

我有一個角度應用程序,它具有(迄今爲止)的插件機制,因此我可以在運行時添加和修改菜單項。要做到這一點,我有一個服務,而插件可以註冊自己,如:動態地包含角度組件

MenuService.addItem(
    "/main/foo", 
    "bar", 
    { 
     title : "Bar", 
     templateUrl : "foo/bar/templates/bar.html", 
     controller : "BarController", 
     controllerAs : "bar", 
     visible : true, 
     [...] 
    } 
); 

,然後我有一個指令來檢索和遍歷項添加一個給定的層級。在內部,這個使用$路由註冊的路線,和模板可以使這樣的結構:

<li menu-item path="/main"> 
    <a href="{{item.path}}">{{item.title}}</a> 
    <ul ng-if="items.children.length>0"> 
     <li menu-item path="{{item.path}}"> 
     </li> 
    </ul> 
</li> 

這一切非常簡單,工作正常。現在,我也想以類似的方式包含整個視圖。大約是這樣的:

<div include-components path="/main/foo"> 
</div> 

我想遍歷在這個路徑中註冊的項目,要麼重複指令是在節點或用正確的模板和控制器設置添加子節點。如果有像上面的一個註冊只有一個項目,所產生的DOM應該是這樣的:

<div 
    include-components 
    path="/main/foo" 
    ng-controller="BarController" 
    ng-include="...template.html"> 

    [included template+controller render here] 

</div> 

或(和子元素):

<div include-components path="/main/foo"> 
    [first registered template /w controller] 
    [second registered template /w controller] 
    [...] 
</div> 

我現在嘗試一種看起來像這樣:

angular.module("angular-plugin").directive(
    "includeComponents", 
    function(MenuService,$route,$templateCache) { 
     console.log($route); 
     return { 
      transclude: 'element', 
      scope: { 
       path : "@" 
      }, 
      link: function(scope, el, attr, ctrl,transclude) { 
       var items = MenuService.get(scope.path); 
       items.forEach(function(each){ 
        [... what?] 
       }); 
      } 
     } 
    } 
}); 

我嘗試了很多的循環中不同的東西......但我已經無法使模板顯示,更不用說在該項目初始化得到控制。我正在看ngView的源代碼,它應該做一些非常相似的事情......但我一直無法使它工作。有任何想法嗎?

回答

0

好吧,現在我花了一些時間看ngView ...我想出了下面的指令。這確實很有效。有什麼遺漏嗎?之後我必須做清理嗎?

angular.module("foobar").directive(
    "includeComponents", 
    function(PluginMenuService,$route,$templateCache,$controller,$compile) { 
     console.log($route); 
     return { 
      scope: { 
       path : "@" 
      }, 
      link: function(scope, el, attr, ctrl,transclude) { 
       var items = PluginMenuService.get(scope.path); 
       if(items.length > 0) { 
        items.forEach(
         function(each) { 
          templ = $templateCache.get(each.templateUrl); 
          var child = el.append(templ); 
          var controller = $controller(each.controller, {}); 
          var link = $compile(child.contents()); 

          childScope = scope.$new(); 

          childScope[each.controllerAs] = controller; 
          childScope["component"] = each; 
          child.data('$ngControllerController', controller); 

          link(childScope); 
         } 
        ); 
       } 
      } 
     } 
    });