将 ng-include 替换为等效代码

Replace ng-include with code equivalent

当用各种 HTML 部分组成我的视图时,我更喜欢在我的标记中放置 ng-include 指令的声明式方法。

但是,我需要动态填充项目的幻灯片放映/旋转木马的第三方小部件不能很好地适应 ng-repeatng-include 的动态 DOM 变化(第三方小部件将在小部件初始化时接受一组子节点出现在 DOM 中,或者接受通过调用 addItem 函数以编程方式添加新项目)。

<!-- this will not work properly, the items collection changes dynamically -->
<div id="slideShowHost">
    <div class="slideShowItem"
        ng-repeat="item in controller.items"
        ng-include="'templates/slideShowItem.html'">
    </div>
</div>

因此,我将用控制器中的等效代码替换 slideShowHost 内容。我使用 RequireJS to load the content of templates/slideShowItem.html as one string, and jQuery 为我的所有项目创建相应的节点。但这还不够,因为我在需要激活的 slideShowItem 模板中使用了 angular 指令。

// I'm using typescript here, but answers may as well use untyped javascript
var slideShowHost = $("#slideShowHost").acmeSlideShow();
require(["slideShowItemTemplate-html"], (itemTemplate: string) =>
{
    for (var i = 0; i < this.items.length; i++)
    {
        let initializedItem = this.initAngularDependentItem(this.items[i], itemTemplate);
        slideShowHost.addAcmeSlideShowItem( initializedItem );
    }
});

...

private initAngularDependentItem(itemModel: any, template: string): any
{
    let itemView = $(template);
    // we have to create a scope here containing the itemModel
    // and we need to init the angular directives inside itemView
    return itemView;
}

对于任何 ng-include,其中包含的部分可能使用任何 angular 指令甚至嵌套 ng-包含?

您需要像这样使用 $compile:

app.controller(function($scope, $compile) {
    var link = $compile(template);
    $('...').append(link($scope));
});

是正确的。我想补充一些细节。

我们需要将 $compile service 注入我们的控制器,以编译 HTML 字符串或 jQuery 创建的 DOM;结果函数必须一起调用到 link 作用域和模板。 因此我们还需要注入 $scope

原始用例包含一个 ng-repeat 指令,它为每个项目创建一个子作用域并将相应的项目添加到其中(additional properties 除外)。因此,我们以编程方式从控制器的 $scope 创建子作用域,以使用具有 link 函数的子作用域。

private static $inject = ["$scope", "$compile"];

...

private initAngularDependentItem(itemModel: any, template: string): any
{
    let itemDOM = $(template);
    let itemScope = this.$scope.$new();
    itemScope.item = itemModel;
    let link = this.$compile(itemDOM);
    let compiledAndLinked = link(itemScope);
    return compiledAndLinked;
}

关于子作用域的一句话: 我的项目模板 top-level 节点使用 ng-controller attribute-directive 为每个项目分配一个 itemController此指令创建新范围。 其后果是,从我上面的代码片段 itemScope 中新创建的每个项目实际上与 itemController 知道为自己的 $scope 的对象不同,但是itemController 的范围是我们创建的对象的 child-scope。记住这一点。当我的父控制器应该从 itemController 据称之前设置的 itemScope 读取属性时,我被绊倒了。

我们可以像这样设置一个共享对象itemScope.sharedObject = {},因为子作用域继承了它,所以两者都是一样的。