2016-02-17 209 views
1

看起來這個問題已經提出了幾次,但沒有正確的答案。我使用ajax(由於某些原因,不使用角路由選擇)加載模板(使用html和腳本)初始化爲div。Angularjs動態地添加控制器

的index.html(主)

<!DOCTYPE html> 
<html ng-app="app" ng-controller="AppCtrl"> 
    <head> 
     <meta charset="utf-8" /> 
     <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 
     <title>Web</title> 
     <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js"></script> 
    </head> 
    <body> 
     <div class="container body-content"> 
      <div class="dynamic-content" > 
       <!-- Loading content Here --> 
      </div> 
      <button ng-click="loadTemplate()">Load Template</button> 
     </div> 

     <script> 
      angular.module('app', []) 
      .controller('AppCtrl', function ($scope) { 
       $scope.someData = {}; 
       $scope.loadTemplate = function() { 
        .... 
        //AJAX to get the templet.html 
        //and load it into .dynamic-content 
        //then applying scope();     
       } 
      }); 
     </script> 
    </body> 
</html> 

template.html(模板)

<div ng-controller="TempCtrl"> 
    <h2>About</h2> 
    <h3>{{total}}</h3> 
    <p>Testing the total</p> 
    <button ng-click="update()">Update</button> 
</div> 

<script> 
    console.log('begin') 
    angular.module('app') 
    .controller('TempCtrl', function ($scope) { 
     $scope.total = 0; 
     console.log('inside') 
     $scope.update = function() { 
      $scope.total += 1; 
     }; 
    }); 
    console.log('end') 
</script> 

當我按一下按鈕Load Template它加載template.html文件中的容器,但我會出錯

Error: [ng:areq] Argument 'TempCtrl' is not a function, got undefined

雖然它被添加到應用程序控制器。

我怎麼能動態地添加了控制器,並把它與動態HTML節點

工作

DEMO這裏https://plnkr.co/edit/EAa9Md36hDzpQ1BgIQKg?p=preview

+1

所以你加載AJAX嘗試向現有模塊添加新控制器,並在控制檯中顯示「開始」和「結束」,表明該腳本正在執行? – Dave

+0

您是否嘗試過將腳本放在模板的HTML部分之前? – Dave

+0

是的控制檯顯示'開始'和'結束',但不是'裏面' – Jag

回答

2

該博客介紹瞭如何使用角度,迫使它加載額外的控制器撥弄它已被自舉之後:

http://www.bennadel.com/blog/2553-loading-angularjs-components-after-your-application-has-been-bootstrapped.htm

當然,這完全是不支持的,並且可以通過改變角度被打破隨時。

但是,在這裏是使用此方法的代碼的更新版本:

var app = angular.module('app', []) 
app.config(
    function($controllerProvider, $provide, $compileProvider) { 
    // Since the "shorthand" methods for component 
    // definitions are no longer valid, we can just 
    // override them to use the providers for post- 
    // bootstrap loading. 
    console.log("Config method executed."); 
    // Let's keep the older references. 
    app._controller = app.controller; 
    app._service = app.service; 
    app._factory = app.factory; 
    app._value = app.value; 
    app._directive = app.directive; 
    app.controller = function(name, constructor) { 
     console.log("controller..."); 
     console.log(name); 
     console.dir(constructor); 
     $controllerProvider.register(name, constructor); 
     return (this); 
    }; 
    // Provider-based service. 
    app.service = function(name, constructor) { 
     $provide.service(name, constructor); 
     return (this); 
    }; 
    // Provider-based factory. 
    app.factory = function(name, factory) { 
     $provide.factory(name, factory); 
     return (this); 
    }; 
    // Provider-based value. 
    app.value = function(name, value) { 
     $provide.value(name, value); 
     return (this); 
    }; 
    // Provider-based directive. 
    app.directive = function(name, factory) { 
     $compileProvider.directive(name, factory); 
     return (this); 
    }; 
    }); 
app.controller('AppCtrl', function($scope, $http, $compile) { 
    $scope.someData = {}; 
    $scope.loadTemplate = function() { 
    $http.get("template.html") 
     .then(function(r) { 
     // load in the html, including the script, which will be executed 
     $(".dynamic-content").html(
      r.data 
     ); 
     // compile the loaded html into an actual template and put it back where it was 
     $(".dynamic-content").html($compile($(".dynamic-content").html())($scope)); 
     }) 
    } 
}); 

請注意,我用jQuery來放置HTML到DOM,導致腳本執行,然後搶HTML回在DOM之外,所以它可以被編譯,之後我又把它放回DOM。

此外,您的模板中有一個未定義的變量。HTML,所以我更新了它看起來是這樣的:

<script> 
    console.log('begin') 
    angular.module('app') 
    .controller('TempCtrl', function ($scope) { 
     $scope.total = 0; 
     console.log('inside') 
     $scope.update = function() { 
      $scope.total += 1; 
     }; 
    }); 
    console.log('end') 
</script> 

<div ng-controller="TempCtrl"> 
    <h2>About</h2> 
    <h3>{{total}}</h3> 
    <p>Testing the total</p> 
    <button ng-click="update()">Update</button> 
</div> 

這裏是一個工作普拉克:http://plnkr.co/edit/cB5N05

+0

完美。這正是我想要的..謝謝戴夫。 – Jag

0

嘗試加載模板控制器中的index.html,而不是在template.html,這種方式在標記正在尋找時已經存在。 index.html中腳本部分:

angular.modules('app', []) 
     .controller('AppCtrl', function ($scope) { 
      $scope.someData = {}; 
      $scope.loadTemplate = function() { 
       .... 
       //AJAX to get the templet.html 
       //and load it into .dynamic-content 
       //then applying scope();     
      } 
     }).controller('TempCtrl', function ($scope) { 
    $scope.total = 0; 
    console.log('inside') 
    $scope.update = function() { 
     total += total; 
    }; 
}); 

編輯: 這是具有引用該應用程序模塊的多個JS文件將是方便的時候,這樣,每個文件所屬的控制器。

+0

我的問題是如何添加**動態控制器**而不是如何獲得這個例子的工作.. – Jag

+0

我只是好奇現在,什麼是你想從這個收到的好處? – Mindbender

+0

像我所說的..我有50 +模板文件與每個模板有自己的控制器(S)。所以不能把它們全部放在一個文件中並立即加載 – Jag

0

更新Dave's例如具有角組件支持

app.config(
    function ($controllerProvider, $provide, $compileProvider) { 

    var app = angular.module('app'); 

    // Let's keep the older references. 
    app._controller = app.controller; 
    app._service = app.service; 
    app._factory = app.factory; 
    app._value = app.value; 
    app._directive = app.directive; 
    app._component = app.component; 

    // Provider-based controller. 
    app.controller = function (name, constructor) { 
     $controllerProvider.register(name, constructor); 
     return (this); 
    }; 
    // Provider-based service. 
    app.service = function (name, constructor) { 
     $provide.service(name, constructor); 
     return (this); 
    }; 
    // Provider-based factory. 
    app.factory = function (name, factory) { 
     $provide.factory(name, factory); 
     return (this); 
    }; 
    // Provider-based value. 
    app.value = function (name, value) { 
     $provide.value(name, value); 
     return (this); 
    }; 
    // Provider-based directive. 
    app.directive = function (name, factory) { 
     $compileProvider.directive(name, factory); 
     return (this); 
    }; 
    // Provider-based component. 
    app.component = function (name, options) { 
     $compileProvider.component(name, options); 
     return (this); 
    }; 

});