【问题标题】:Replace ng-include node with template?用模板替换 ng-include 节点?
【发布时间】:2013-05-05 23:41:48
【问题描述】:

有点新的角度。是否可以用包含的模板的内容替换 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>

【问题讨论】:

  • 从'test.html'中删除单引号以使用模板而不是url
  • 阅读 ng-include 文档的 cmets,似乎它用单引号包围了字符串,而不是 url。另外,相关stackoverflow question
  • 您正在阅读文档并将您的帖子链接到反向

标签: angularjs


【解决方案1】:

感谢@user1737909,我意识到 ng-include 不是可行的方法。指令是更好的方法,也更明确。

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

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

在html中:

<blah></blah>

【讨论】:

  • 谢谢!正在寻找一个 ng-include 解决方案,但这帮助我意识到指令更好
  • 请记住,模板中的replace:true 是marked for deprecation。由于弃用状态,我会避免使用此解决方案。
  • @PeterV.Mørch 谢谢。对于那些感兴趣的人,这是提交:github.com/angular/angular.js/commit/…。由于它的复杂性(也许还有其他原因),它似乎已被弃用。
【解决方案2】:

我遇到了同样的问题,但仍然希望 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+
  • 我在一个类似的问题中引用了这个答案:angularjs - Avoid using extra DOM nodes when using nginclude - Stack Overflow
  • 这适用于 Angular 1.2.5+。对于 1.2.4,如果您有一个 ng-include 而 ng-include 另一个,它会失败。我猜是因为#5247,但我不确定。请自行查看Changelog。这是一个Plunkr,用 1.2.4 演示了这个问题(更改为 angular 1.2.5 并查看它的工作原理!:-)
  • 请注意,这样的 DOM 操作非常 hacky。如果包含模板的根元素使用类似 ng-repeat 的东西,就会出现问题。它将无法在 DOM 中插入结果。
  • 请看我对此的回答,这将失败,因为预链接功能已经在子元素中运行。
【解决方案3】:

另一种选择是编写自己的简单替换/包含指令,例如

    .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>

【讨论】:

    【解决方案4】:

    我遇到了同样的问题,我的第 3 方 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>
    

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

    【讨论】:

      【解决方案5】:

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

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

      .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() );
      【解决方案6】:

      这是替换孩子的正确方法

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

      【讨论】:

      • 我包含的部分 html 有一些 ng-repeat,这是解决它们的唯一答案!非常感谢。
      • 我不得不将函数内容从compile移动到link,因为我的元素在编译阶段是空的。
      【解决方案7】:

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

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

      按原方式使用,只需添加“replace”属性即可:

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

      【讨论】:

        猜你喜欢
        • 2016-12-24
        • 1970-01-01
        • 2017-12-05
        • 2017-02-07
        • 2017-01-12
        • 1970-01-01
        • 1970-01-01
        • 2014-01-15
        • 2016-03-09
        相关资源
        最近更新 更多