Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
209 views
in Technique[技术] by (71.8m points)

javascript - How to bind an AngularJS controller to dynamically added HTML?

For this scenario, I have a page of HTML with some AngularJS directives, controllers, etc.

Something like this:

<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>

Notice that there is no ng-app directive on the page. I am not relying on auto-bootstrapping, but rather I am using the manual bootstrapping method.

angular.bootstrap(document, ['myApp']);

First, I create the module which will be bootstrapped to the document. Then as a dynamically determined list of dependencies are loaded, I attach some services, controllers, etc. Once everything is ready I call the bootstrap method.

This all works fine, until JavaScript outside of AngularJS appends to the DOM at the ...new HTML here... location. The new HTML is not processed by AngularJS.

My understanding is that you need to call $scope.$apply() or $digest() or something to get AngularJS to recognize the new HTML. However, in my example there is no controller around the new HTML coming in. The incoming HTML may look like this:

  <div ng-controller="myOtherCtrl">
     <h2>{{model.title}}</h2>
  </div>

In other words, it is relying on a different controller in the app module.

  • I can't call the angular.bootstrap method again, because the page is already bound.
  • I can't call $scope.$apply from inside the controller because the whole point is that controller code isn't being called.
  • I don't see a way to get a reference to the controller in order to re-apply or refresh it.

I have read the Ifeanyi Isitor lazy loading post and the Ben Nadel post, yet they don't seem to address HTML loaded outside the context of an existing controller.

It isn't an option for me to use AngularJS directives to handle the DOM manipulation. It is a separate part of the architecture which uses ExtJS as the framework for injecting the new DOM elements. This means I can't use ngInclude for example.

It would seem like I could just call angular.module('myApp').$refresh(); or .$apply() but that isn't an option. What am I missing?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I've faced the same issue, here's what I came up with :

<div id="mController" ng-controller="mainController">
</div>

<div id="ee">
  2nd controller's view should be rendred here
</div>

and calling setCnt() function will inject and compile the html, and it will be linked to the 2nd controller:

var app = angular.module('app', []);

function setCnt() {
  // Injecting the view's 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";
});

here's an example to test this : https://snippet.run/x4bc

hope this helps.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...