【问题标题】:How to bind an AngularJS controller to dynamically added HTML?如何将 AngularJS 控制器绑定到动态添加的 HTML?
【发布时间】:2013-12-18 06:59:18
【问题描述】:

对于这种情况,我有一个带有一些 AngularJS 指令、控制器等的 HTML 页面。

类似这样的:

<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']);

首先,我创建了将被引导到文档的模块。然后在加载动态确定的依赖项列表时,我附加一些服务、控制器等。一切准备就绪后,我调用引导方法。

这一切都很好,直到 AngularJS 之外的 JavaScript 在 ...new HTML here... 位置附加到 DOM。 AngularJS 不处理新的 HTML。

我的理解是你需要调用$scope.$apply()$digest() 或其他东西来让AngularJS 识别新的HTML。但是,在我的示例中,新的 HTML 周围没有控制器。传入的 HTML 可能如下所示:

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

换句话说,它依赖于应用模块中的不同控制器。

  • 我无法再次调用angular.bootstrap 方法,因为页面已经绑定。
  • 我不能从控制器内部调用$scope.$apply,因为关键是控制器代码没有被调用。
  • 我看不到获取控制器引用以重新应用或刷新它的方法。

我已经阅读了Ifeanyi Isitor lazy loading postBen Nadel post,但它们似乎没有解决在现有控制器的上下文之外加载的 HTML。

我不能选择使用 AngularJS 指令来处理 DOM 操作。它是架构的一个独立部分,它使用 ExtJS 作为注入新 DOM 元素的框架。这意味着我不能使用 ngInclude 例如。

看起来我可以打电话给angular.module('myApp').$refresh();.$apply(),但这不是一个选择。我错过了什么?

【问题讨论】:

  • 我没有任何同时使用 extJS 和 angular 的经验,所以恐怕我不能再帮你了。不过要记住一件事,AngularJS 和 ExtJS 都是设计为 webapp 需要的唯一框架的框架。使用两个框架意味着每个客户端都必须下载更多数据,这通常是有问题的,尤其是在移动设备上。看看您是否可以将应用程序的 ExtJS 部分转换为 angularjs,反之亦然。
  • ExtJS 仅在创作体验期间发挥作用,我无法选择删除它。我想使用 Angular 的模块化、双向绑定、可测试性等。在这种情况下,ExtJS 所做的只是将一些 HTML 渲染到 DOM 中的某个位置。让 Angular 认识到发生了变化似乎是一个挑战。

标签: javascript angularjs


【解决方案1】:

我遇到了同样的问题,这是我想出的:

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

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

调用 setCnt() 函数将注入并编译 html,并将链接到第二个控制器:

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";
});

这里有一个例子来测试这个:https://snippet.run/x4bc

希望这会有所帮助。

【讨论】:

  • 干得好,尽管$scope.$apply(); 在您的示例中没有用处。
【解决方案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);

【讨论】:

  • 最后一个加一个 templateEL 错字
  • 这是一个不错的答案,也是最接近我所寻找的答案,但缺少重要的警告,即您必须已经在“角度世界”中才能访问诸如“$rootScope”之类的东西”和“$控制器”。如果您尝试在没有其他控制器或角度指令的页面上执行此操作(甚至可能没有 ng-app),那么此回复将使您到达那里:stackoverflow.com/a/28766083/999256
【解决方案3】:

您可能想要使用$compile 服务。这就是 Angular 首先要做的事情。

还有本指南:http://docs.angularjs.org/guide/compiler

【讨论】:

    【解决方案4】:

    我遇到了同样的问题。 这对我有用:https://docs.angularjs.org/api/ng/function/angular.injector

    【讨论】:

    • 你用 angular $injector 做了什么?更多细节将不胜感激
    【解决方案5】:

    我认为ng-include 可能会对您有所帮助,它将部分页面加载到元素中并像您网页的任何其他部分一样编译和处理它。

    如果此元素是您的网络应用程序的主视图,并且您希望根据 url 加载不同的“屏幕”,ng-view 可能会派上用场。

    【讨论】:

    • 谢谢,我更新了问题以澄清什么是注入 DOM 元素。我认为我不能依赖 ng-include 因为它需要加载和注入的 src URL。 ng-view 可能值得深入研究。我唯一担心的是我真的不知道 HTML 将在哪里注入 DOM,所以除非我可以将 ng-view 指令放在 body 标记上,否则我认为它不会起作用。
    【解决方案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

    【讨论】:

      猜你喜欢
      • 2013-11-19
      • 2018-01-29
      • 1970-01-01
      • 1970-01-01
      • 2017-03-29
      • 2012-07-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多