Подтвердить что ты не робот

Как связать контроллер 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 и сообщение

4b9b3361

Ответ 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

Ответ 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