Как связать контроллер AngularJS с динамически добавленным HTML?
Для этого сценария у меня есть страница HTML с некоторыми директивами AngularJS, контроллерами и т.д.
Что-то вроде этого:
<html>
<body>
<div ng-controller="myCtrl">
<ul><li ng-repeat="item in items">{{item.name}}</li></ul>
</div>
<div class="placeholder">
...new HTML here...
</div>
</body>
</html>
Обратите внимание, что на странице нет директивы ng-app
. Я не полагаюсь на автоматическую загрузку, но я использую метод ручной начальной загрузки.
angular.bootstrap(document, ['myApp']);
Сначала я создаю модуль, который будет загружен в документ. Затем, когда загружается динамически определенный список зависимостей, я прикрепляю некоторые службы, контроллеры и т.д. Как только все будет готово, я вызываю метод начальной загрузки.
Все это прекрасно работает, пока JavaScript за пределами AngularJS не добавится к DOM в ...new HTML here...
. Новый HTML не обрабатывается AngularJS.
Я понимаю, что вам нужно вызвать $scope.$apply()
или $digest()
или что-то, чтобы заставить AngularJS распознавать новый HTML. Однако в моем примере нет контроллера вокруг нового HTML-кода. Входящий HTML-код может выглядеть так:
<div ng-controller="myOtherCtrl">
<h2>{{model.title}}</h2>
</div>
Другими словами, он полагается на другой контроллер в модуле приложения.
- Я не могу снова вызвать метод
angular.bootstrap
, потому что страница уже связана.
- Я не могу вызывать
$scope.$apply
изнутри контроллера, потому что все дело в том, что код контроллера не вызывается.
- Я не вижу способа получить ссылку на контроллер, чтобы повторно применить или обновить его.
Я прочитал сообщение Ifeanyi Isitor lazy loading post и сообщение
Ответы
Ответ 1
Я столкнулся с той же проблемой, вот что я придумал:
<div id="mController" ng-controller="mainController">
</div>
<div id="ee">
2nd controller view should be rendred here
</div>
и вызов функции setCnt() будет вставлять и компилировать html, и он будет связан со вторым контроллером:
var app = angular.module('app', []);
function setCnt() {
// Injecting the view html
var e1 = angular.element(document.getElementById("ee"));
e1.html('<div ng-controller="ctl2">my name: {{name}}</div>');
// Compile controller 2 html
var mController = angular.element(document.getElementById("mController"));
mController.scope().activateView(e1);
}
app.controller("mainController", function($scope, $compile) {
$scope.name = "this is name 1";
$scope.activateView = function(ele) {
$compile(ele.contents())($scope);
$scope.$apply();
};
});
app.controller("ctl2", function($scope) {
$scope.name = "this is name 2";
});
вот пример, чтобы проверить это: http://refork.com/x4bc
надеюсь, что это поможет.
Ответ 2
Давайте возьмем небольшой шаблон
var template = '<div ng-controller = "someController">';
template += '<All html you want to add>';
template += '</div>';
Теперь, если вы хотите добавить этот шаблон, вам нужно сделать следующие две вещи:
1) Создайте ваш контроллер с помощью $controller
2) Скомпилируйте свой шаблон.
//this creates a new scope
var $scope = $rootScope.$new();
//Controller initialize with $scope
$controller('someController',{$scope,$scope});
var templateEl = angular.element(template);
//Now compile the template with scope $scope
$compile(templateEl)($scope);
angular.element('body').append(templateEL);
Ответ 3
Возможно, вы захотите использовать службу $compile
. То, что angular делает на первом месте.
И также это руководство: http://docs.angularjs.org/guide/compiler
Ответ 4
У меня была та же проблема.
Это сработало для меня: https://docs.angularjs.org/api/ng/function/angular.injector
Ответ 5
Я думаю, ng-include может помочь вам, он загружает частичную страницу в элемент и компилирует и обрабатывает ее, как и любую другую часть вашего веб-страницы.
Если этот элемент является основным видом вашего веб-приложения, и вы хотите загрузить в него разные "экраны", в зависимости от URL-адреса, ng-view может пригодиться.
Ответ 6
Я следил за этим процессом и работал у меня:
// Some variables
var $controllerElement = angular.element('css-selector-to-the-controller-element');
var $appElement = angular.element('css-selector-to-ng-app-element');
// compiling and applying / digesting the scope.
$appElement.injector().invoke(function($compile) {
var scope = $controllerElement.scope();
$compile($controllerElement)(scope);
scope.$apply();
});
Ссылка: Angular.injector