将ng-include替换为等效的代码

时间:2016-01-14 10:13:07

标签: javascript angularjs angularjs-directive angularjs-ng-include

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

然而,我需要动态填充项目的slideShow / carousel的第三方窗口小部件与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 templates / slideShowItem.html 的内容加载为一个字符串,并使用jQuery为其创建所有项目的相应节点。但这还不够,因为我在 slideShowItem 模板中使用了需要生命的角度指令。

// 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;
}

对于包含部分可能使用任何 angular 指令甚至嵌套 ng-includes 的任何ng-include,哪个代码是正确且可靠的替代品?

2 个答案:

答案 0 :(得分:1)

你需要像这样使用$ compile:

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

答案 1 :(得分:0)

answer given by jcubic是正确的。我想补充一些细节。

我们需要将$compile service注入我们的控制器,以编译HTML字符串或jQuery创建的DOM;必须调用生成的函数以将范围和模板链接在一起。 因此,我们还需要注入$scope

原始用例包含ng-repeat指令,该指令为每个项创建一个子范围,并将相应的项添加到其中(除了additional properties)。因此,我们以编程方式从控制器的$ scope创建子范围,以使用具有链接功能的子范围。

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

关于子范围的一句话: 我的项目模板顶级节点使用ng-controller attribute-directive为每个项目分配 itemController 此指令创建新范围。 其分支是从我上面的代码片段中创建的每个项目itemScope实际上不是 itemController 将知道它自己的$ scope的对象,而是< em> itemController 的范围是我们创建的对象的子范围。记在脑子里。当我的父控制器应该从itemScope中读取 itemController 之前据称设置的属性时,我绊倒了这个。

我们可以设置像itemScope.sharedObject = {}这样的共享对象,因为childscope会继承它,所以它们都是相同的。