用模板替换ng-include节点?


85

有点新的角。是否可以用包含的模板的内容替换ng-include节点?例如,使用:

<div ng-app>
    <script type="text/ng-template" id="test.html">
        <p>Test</p>
    </script>
    <div ng-include src="'test.html'"></div>
</div>

生成的html是:

<div ng-app>
    <script type="text/ng-template" id="test.html">
        <p>Test</p>
    </script>
    <div ng-include src="'test.html'">
        <span class="ng-scope"> </span>
        <p>Test</p>
        <span class="ng-scope"> </span>
    </div>
</div>

但是我想要的是:

<div ng-app>
    <script type="text/ng-template" id="test.html">
        <p>Test</p>
    </script>
    <p>Test</p>
</div>

1
从中删除单引号'test.html'以使用模板而不是url
charlietfl 2013年

1
阅读ng-include的文档注释,似乎它用单引号将模板引起来,而将url括起。另外,相关的stackoverflow问题
SunnySydeUp,2013年

您正在阅读文档,并发布了与反向链接的链接
charlietfl 2013年

Answers:


134

我遇到了同样的问题,但仍然希望ng-include的功能包括动态模板。我正在构建一个动态的Bootstrap工具栏,我需要更清洁的标记才能正确应用CSS样式。

这是我为感兴趣的人提供的解决方案:

HTML:

<div ng-include src="dynamicTemplatePath" include-replace></div>

自定义指令:

app.directive('includeReplace', function () {
    return {
        require: 'ngInclude',
        restrict: 'A', /* optional */
        link: function (scope, el, attrs) {
            el.replaceWith(el.children());
        }
    };
});

如果在上面的示例中使用了此解决方案,则将scope.dynamicTemplatePath设置为“ test.html”将产生所需的标记。


需要angular v1.2 +
colllin 2014年


这适用于角度1.2.5+。对于1.2.4,如果您有一个ng-include,而另一个ng-includes则失败。由于#5247我正在猜测,但我不确定。自己查看Changelog。这是一个Plunkr,用1.2.4演示了这个问题(更改为1.2.5角度,然后看到它起作用了!:-)
Peter

9
请注意,这样的DOM操作相当棘手。如果包含模板的根元素使用ng-repeat之类的东西,则会出现问题。它将无法在DOM中插入结果。
古里亚

1
请查看我对此的回答,这将失败,因为预链接功能已经在子元素中运行。
塞巴迪卡卡2015年

28

因此,感谢@ user1737909,我已经意识到ng-include不是行之有效的方法。指令是更好的方法,也更明确。

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

App.directive('blah', function() {
    return {
        replace: true,
        restrict: 'E',  
        templateUrl: "test.html"
    };
});

在html中:

<blah></blah>

2
谢谢!一直在寻找ng-include解决方案,但这帮助我意识到指令更好
Matt Kim

请记住,replace:true在模板中已标记要弃用。由于淘汰状态,我会避免使用此解决方案。
Peter V.Mørch2014年

@PeterV.Mørch谢谢。对于那些感兴趣的人,这是提交:github.com/angular/angular.js/commit/…。由于它的复杂性(也许还有其他原因),它似乎已被弃用。
SunnySydeUp 2014年

15

我有同样的问题,我的第三方CSS样式表不喜欢多余的DOM元素。

我的解决方案非常简单。只需向上移动ng-include 1。所以代替

<md-sidenav flex class="md-whiteframe-z3" md-component-id="left" md-is-locked-open="$media('gt-md')">
  <div ng-include="myService.template"></span>
</md-sidenav>

我只是做了:

<md-sidenav flex class="md-whiteframe-z3" md-component-id="left" md-is-locked-open="$media('gt-md')" ng-include="myService.template">
</md-sidenav>

我敢打赌,这在大多数情况下都是可行的,即使从技术上讲不是问题所要问的。


10

另一种选择是编写自己的简单replace / include指令,例如

    .directive('myReplace', function () {
               return {
                   replace: true,
                   restrict: 'A',
                   templateUrl: function (iElement, iAttrs) {
                       if (!iAttrs.myReplace) throw new Error("my-replace: template url must be provided");
                       return iAttrs.myReplace;
                   }
               };
           });

然后将其使用如下:

<div my-replace="test.html"></div>

9

这是替换孩子的正确方法

angular.module('common').directive('includeReplace', function () {
    return {
        require: 'ngInclude',
        restrict: 'A',
        compile: function (tElement, tAttrs) {
            tElement.replaceWith(tElement.children());
            return {
                post : angular.noop
            };
        }
    };
});

4
我包含的部分html得到了ng-repeat,这是解决它们的唯一答案!非常感谢。
Saad Benbouzid

我必须将函数内容从compile移到link,因为在编译阶段我的元素为空。
itachi

3

以下指令扩展了ng-include本机指令功能。

当内容准备好并加载时,它将添加一个事件侦听器以替换原始元素。

以原始方式使用它,只需添加“替换”属性:

<ng-include src="'src.html'" replace></ng-include>

或带有属性符号:

<div ng-include="'src.html'" replace></div>

这是指令(请记住将“ include-replace”模块作为依赖项包括在内):

angular.module('include-replace', []).directive('ngInclude', function () {
    return {
        priority: 1000,
        link: function($scope, $element, $attrs){

            if($attrs.replace !== undefined){
                var src = $scope.$eval($attrs.ngInclude || $attrs.src);

                var unbind = $scope.$on('$includeContentLoaded', function($event, loaded_src){
                    if(src === loaded_src){
                        $element.next().replaceWith($element.next().children());
                        unbind();
                    };
                });
            }
        }
    };
});

2

我会选择比@Brady Isom提供的解决方案更安全的解决方案。

我更喜欢依靠onload给出的选项ng-include来确保在尝试删除模板之前已加载模板。

.directive('foo', [function () {
    return {
        restrict: 'E', //Or whatever you need
        scope: true,
        template: '<ng-include src="someTemplate.html" onload="replace()"></ng-include>',
        link: function (scope, elem) {
            scope.replace = function () {
                elem.replaceWith(elem.children());
            };
        }
    };
}])

不需要第二个指令,因为所有内容都在第一个指令内处理。


注意,使用angular 1.5时,指令元素中的第一个子元素是注释。因此,我确保获得ng-include元素,然后将其替换为其子元素: let ngInclude = angular.element( element[ 0 ].querySelector( 'ng-include' ) ); ngInclude.replaceWith( ngInclude.children() );
Mattijs
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.