关于angularjs:用模板替换ng-include节点?

Replace ng-include node with template?

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

1
2
3
4
    <script type="text/ng-template" id="test.html">
        <p>
Test
</p>

生成的HTML是:

1
2
3
4
5
6
7
8
9
10
11
    <script type="text/ng-template" id="test.html">
        <p>
Test
</p>
   
   
        <span class="ng-scope"> </span>
        <p>
Test
</p>
        <span class="ng-scope"> </span>

但我想要的是:

1
2
3
4
5
6
7
8
    <script type="text/ng-template" id="test.html">
        <p>
Test
</p>
   
    <p>
Test
</p>


我也遇到过同样的问题,仍然希望ng的特性包括一个动态模板。我正在构建一个动态引导工具栏,我需要更清晰的标记来正确应用CSS样式。

以下是我为感兴趣的人提出的解决方案:

HTML:

1
 

自定义指令:

1
2
3
4
5
6
7
8
9
app.directive('includeReplace', function () {
    return {
        require: 'ngInclude',
        restrict: 'A', /* optional */
        link: function (scope, el, attrs) {
            el.replaceWith(el.children());
        }
    };
});

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


所以多亏了@user1737909,我才意识到ng include不是一个好方法。指令是更好的方法,更明确。

1
2
3
4
5
6
7
8
9
var App = angular.module('app', []);

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

在HTML中:

1
<blah></blah>


我也有同样的问题,我的第三方CSS样式表不喜欢额外的dom元素。

我的解决方案非常简单。只需将ng include 1向上移动。因此,而不是

1
2
3
<md-sidenav flex class="md-whiteframe-z3" md-component-id="left" md-is-locked-open="$media('gt-md')">
  </span>
</md-sidenav>

我只是这样做了:

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

我敢打赌,这在大多数情况下都会奏效,即使从技术上讲,这并不是问题所在。


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

1
2
3
4
5
6
7
8
9
10
    .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;
                   }
               };
           });

然后按如下方式使用:

1
 

这是更换孩子的正确方法

1
2
3
4
5
6
7
8
9
10
11
12
angular.module('common').directive('includeReplace', function () {
    return {
        require: 'ngInclude',
        restrict: 'A',
        compile: function (tElement, tAttrs) {
            tElement.replaceWith(tElement.children());
            return {
                post : angular.noop
            };
        }
    };
});


以下指令扩展了ng,包括本机指令功能。

它添加了一个事件监听器,在内容准备好并加载后替换原始元素。

以原始方式使用,只需添加"replace"属性:

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

或使用属性符号:

1
 

以下是指令(请记住将"include replace"模块作为依赖项包括在内):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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();
                    };
                });
            }
        }
    };
});


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

我更喜欢使用ng-include提供的onload选项,以确保在尝试删除模板之前加载模板。

1
2
3
4
5
6
7
8
9
10
11
12
.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());
            };
        }
    };
}])

不需要第二个指令,因为一切都在第一个指令中处理。