AngularJS动态添加控制器 [英] Angularjs add controller dynamically
问题描述
看起来这个问题已经问了好几次了,但是没有正确的答案.
我的情况:我正在使用ajax(出于某种原因未使用角度路由模板)将模板(带有html和脚本)初始化为div.
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
文件加载到容器中,但是出现错误
错误:[ ng:areq ]参数'TempCtrl'不是一个函数,没有定义
尽管已添加到应用程序控制器中.
如何动态添加控制器并使其与动态html节点一起使用
此处演示 https://plnkr.co/edit/EAa9Md36hDzpQ1BgIQKg?p =预览
此博客介绍了如何在启动后摆弄angular强制其加载其他控制器:
当然,这是完全不受支持的,并且随时可以通过更改角度来破坏.
但是,这是使用此方法的代码的更新版本:
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中./p>
此外,您的template.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
It looks like this questions already asked few times but there is no correct answer to it.
my case: i'm loading a template (with html and script) init to div using ajax (not using angular routing temple for some reason).
index.html (main)
<!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 (template)
<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>
when i click the button Load Template
it loads the template.html
file in to container but i'm getting error
Error: [ng:areq] Argument 'TempCtrl' is not a function, got undefined
though its being added to app controllers.
How can i add controllers dynamically and get it work with dynamic html nodes
DEMO HERE https://plnkr.co/edit/EAa9Md36hDzpQ1BgIQKg?p=preview
This blog describes how to fiddle with angular to force it to load additional controllers after it has been bootstrapped:
Of course, this is completely unsupported, and could be broken by changes to angular at any time.
But, here is an updated version of your code using this method:
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));
})
}
});
Note that I used jQuery to place the HTML into the DOM, causing the script to execute, then to grab the HTML back out of the DOM so it could be compiled, after which I placed it back in the DOM again.
Also, there is an undefined variable in your template.html, so I updated it to look like this:
<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>
Here is a working plunk: http://plnkr.co/edit/cB5N05
这篇关于AngularJS动态添加控制器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!