【问题标题】:Custom ngInclude : variable in template not replaced自定义 ngInclude :模板中的变量未替换
【发布时间】:2016-06-20 23:22:17
【问题描述】:

我正在尝试创建一个指令来加载自定义模板,但如果自定义不存在,请加载默认模板。

这是我的代码:

HTML:

<my-include src="path/to/template.html"></my-include>

指令:

angular.module('app')

    .directive("myInclude", function ($compile) {
        return {
            restrict: 'CAE',
            replace: true,
            scope: {
                src: '@',
            },
            link: function (scope, iElement, iAttrs, controller) {
                scope.$on("$includeContentError", function (event, args) {

                    scope.src = args.replace('/custom', '').replace("'", '');
                });
                scope.$on("$includeContentLoaded", function (event, args) {

                    scope.src = args.replace("'", '');
                });
            },
            template: '<div class="include-container" ng-include="src"></div>'
        };
    })
;

我遇到的问题是...我的模板没有显示... 当我调试它时,它会转到指令并替换 src。但我得到的html如下:

<div class="include-container ng-scope" ng-include="src" src="path/to/template.html"><div class="main-information-content ng-scope">
</div>

知道如何解决这个问题吗?我猜这是因为“ng-include ='src'”,其中“src”没有被路径替换......如何修复它?

编辑:

我试图把这个模板:

template: '<div class="include-container" ng-include="{{ src }}"></div>'

但我收到此错误:

错误:[$parse:syntax] http://errors.angularjs.org/1.5.0/$parse/syntax?p0=%7B&p1=invalid%20key&p2=2&p3=%7B%7Brc%20%7D%7D&p4=%7B%src%20%7D%7D

编辑 2: 当我把它作为模板时:

template: '<div class="include-container" ng-include="tmpSrc"></div>'

并用scope.tmpSrc替换scope.src,ng-include值现在很好,但是我的html视图中替换的模板被注释掉了......为什么?

编辑 3:

使用你的 sn-p,这是我需要做的一个想法:

  angular
    .module('app', [])
    .directive("myInclude", function($compile) {
      return {
        restrict: 'CAE',
        replace: true,
        scope: {
          src: '@',
        },
        link: function(scope, iElement, iAttrs, controller) {
          scope.$on("$includeContentError", function() {
            scope.src = 'error-template.html';
          });
          scope.$on("$includeContentLoaded", function(event, args) {
            // No need to do anything - the content has loaded.
          });
        },
        template: '<div class="include-container" ng-include="src"></div>'
      };
    })

  .controller('mainController', ['$scope', '$http',
    function($scope, $http) {

      // Is the content loaded ?
      $scope.state = 'loading';
    }
  ]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js"></script>

<div ng-app="app">
  <div>
    This will show the correct template:
    <my-include src="path/to/template.html"></my-include>
  </div>

  <div>
    This will show an error template:
    <div ng-controller="mainController as main">
      <my-include src="something/that/does/not/exist.html"></my-include>
    </div>
  </div>

  <script type="text/ng-template" id="path/to/template.html">

    <h1>I want to display state : {{ state }}</h1>
  </script>
  <script type="text/ng-template" id="error-template.html">
    <h1>Hello from "error-template.html"</h1>
  </script>
</div>

【问题讨论】:

  • 也尝试在compile 阶段而不是在post link 中执行此操作
  • 我该怎么做?抱歉,还不是 angularjs 专家!

标签: javascript html angularjs angularjs-directive


【解决方案1】:

基本上,您想要“增强” ngInclude 以支持和错误回退,而不是创建新范围(因为这可能会导致 scope's prototypical inheritance 出现某些“错误”,例如 this onethis one等)。

我已经创建了一个执行此操作的指令。它加载通过 src 属性指定的自定义模板,并支持通过 error-src 属性指定的后备模板选项。

我不太喜欢这种方法,尤其是当您在模板中添加依赖于其父级的逻辑时。您应该将模板逻辑委派给重点突出且可重用的指令。这将有助于测试过程并隐藏实现细节。

    angular
      .module('app', [])
      .controller('MainController', ['$scope',
        function($scope) {
          // Is the content loaded ?
          $scope.state = 'loading';
        }
      ])
      .directive('staticNgInclude', ['$compile', '$http', '$templateCache',
        function($compile, $http, $templateCache) {
          return {
            link: function(scope, iElement, iAttrs) {
              if (angular.isUndefined(iAttrs.src)) {
                throw 'staticNgInclude requires the src attribute.'
              }

              $http
                .get(iAttrs.src, {
                  cache: $templateCache
                }).then(function(response) {
                  // Hooray, the template was found!
                  $compile(iElement.html(response.data).contents())(scope);
                }, function() {
                  // Fetch the error template!
                  $http
                    .get(iAttrs.errorSrc || 'error-template.html', {
                      cache: $templateCache
                    }).then(function(response) {
                      $compile(iElement.html(response.data).contents())(scope);
                    });
                });
            },
            replace: false,
            restrict: 'E'
          };
        }
      ]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js"></script>

<div ng-app="app">
  <div ng-controller="MainController">
    This will show the correct template:
    <static-ng-include src="path/to/template.html"></static-ng-include>
  </div>
  <div>
    This will show an error template:
    <static-ng-include src="something/that/does/not/exist.html"></static-ng-include>
  </div>
  <script type="text/ng-template" id="path/to/template.html">
    <h1>I want to display state : {{ state }}</h1>
  </script>
  <script type="text/ng-template" id="error-template.html">
    <h1>Hello from "error-template.html"</h1>
  </script>
</div>

【讨论】:

  • 我已经试过了,但是我得到一个角度错误,我的模板仍然没有显示。我会用我得到的错误更新我的问题
  • 我添加了一个我猜你想要实现的示例。
  • 基本上,我正在做的是允许开发人员使用自定义模板,以覆盖默认模板 - 为此,他们必须将自定义模板放在“自定义”文件夹下。如果包含没有找到具有相同视图名称的“自定义”模板,它会加载默认模板 - 这就是我的 .replace('/custom', '') 现在我的模板已加载......但是其控制器中的变量似乎不起作用(我有一个“状态”变量,它显示加载程序或内容。我只是一个空白。在调试器中,所有代码都被注释掉了......感谢您的帮助伙伴!
  • 请注意,您的指令具有隔离范围。 “隔离”作用域与普通作用域的不同之处在于它在原型上并不从其父作用域继承。如果您可以包含我们可以运行的代码 sn-p 那就太好了。
  • 我在我的问题中输入了一个代码 sn-p。希望你有足够的信息!
猜你喜欢
  • 2023-04-04
  • 1970-01-01
  • 2015-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-09
  • 2017-05-19
  • 1970-01-01
相关资源
最近更新 更多