javascript - Angular 表达式选择一个指令

标签 javascript angularjs

我需要呈现一个 Angular Directive(指令),通过调用先前在变量(通常在 Controller 中声明)定义的字符串来选择它。尽管这样的变量可以作为 Angular 表达式访问,但当我尝试使用它来选择指令时它不起作用:

<!DOCTYPE html>
<html ng-app="app">
<body ng-controller="TextController">

<!-- item.dir is accessible: -->
<div>Value of item: {{item.dir}}</div>

<!-- It works. the directive "hello" is rendered -->
<div class="hello"></div>
<hello></hello>

Here you should see additional text:
<!-- Doesn't work item.dir is not recognized-->
<!-- as a class -->
<div class="{{item.dir}}"></div>

<!-- as an attribute-->
<div {{item.dir}}></div>

<!-- trying ng-class (it fails)-->
<div ng-class="item.dir"></div>

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.5/angular.min.js"></script>

<script>

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

  // The directive to render
  appModule.directive('hello', function() {
        return {
          restrict: 'ACE',
          template: '<div>works: Transcoded text</div>',
          replace: true
        };
      });

  appModule.controller('TextController', function ($scope) {
    $scope.item = {dir: 'hello'}; // the name of the directive, the idea is to use it for referring to many future directives.
  });
</script>
</body>
</html>

下面是一段代码:http://plnkr.co/edit/tM73sY3vTfPFHmn6iCYE?p=preview

那么,我缺少什么?使用指令时如何使用字符串插值来获取 Angular?谢谢!

最佳答案

要使指令起作用,Angular 需要编译您的 html(加载页面时自动完成的操作)。

有一种方法可以自由控制实例化哪个指令有点像把地毯拉到脚下,这是非典型的。问题之一是编译“破坏”了内部绑定(bind)/观察者数据和一些原始 DOM,因此没有足够的信息来“重新编译”DOM 节点。

注意:您不能使用这种类型的绑定(bind)更改属性或元素名称(仅属性值):{{ }} 但是 ng-class="..."和 class="{{...}} "有效。

我不明白你到底想达到什么目的。如果真正的目的是修改 item.dir 的值并让 Angular“重新配置”您的应用程序,那是“可能的”,但我高度怀疑它会导致“状态”缺陷。

不过,这里有一个有效的“hack”,可以“记住”原始 DOM html 并在需要时重新编译它。这是在 2 个编译阶段完成的:第一阶段是恢复原始绑定(bind),第二阶段在 $digest 循环之后运行,以便原始绑定(bind)完成从范围填充类名(即使 item.dir 生效)。缺点当然是如果您对封闭的 DOM 进行了修改,这将清除它们!或者,可能只记住特定属性并仅恢复“那个”,同时保持 DOM 的其他部分完好无损(但可能会产生其他问题)。

  appModule.directive('forceRecompilation', ['$timeout', '$compile', function($timeout, $compile) {
    return {
      restrict: 'A',
      link: function(scope, element, attr) {

        var originalHtml = element.html();

        scope.$watch(attr.forceRecompilation, function(){
            // restore original HTML and compile that
            element.html(originalHtml);
            $compile(element.contents())(scope);

            // wait for all digest cycles to be finished to allow for "binding" to occur
            $timeout(function(){
              // recompile with bounded values
              $compile(element.contents())(scope);
            });
          });
      }
    };
  }]);

...用作要操作的 DOM 部分的封闭标记。当表达式发生变化时,它将“恢复并重新编译”它下面的所有内容。 (此处为“item.dir”):

<div force-recompilation="item.dir">
    <div class="{{item.dir}}">
</div>

笨蛋:http://plnkr.co/edit/TcMhzFpErncbHSG6GgZp?p=preview

在 plunker 中,有 2 个指令“hello”和“hello2”。将文本更改为“hello”并变回“hello2”以查看效果。

编辑:以下是一个指令,允许插入标记按照下面的注释中的描述进行编译。这只是 Angularjs - inline directives with ng-bind-html-unsafe 的略微修改版本

  angular.module('bindHtmlExample', ['ngSanitize'])
    .controller('ExampleController', ['$scope',
      function($scope) {

        $scope.test = false;
        $scope.dir = "ng-click";
        $scope.clicked = function() {
          $scope.test = !$scope.test
        }

        $scope.myHTML =
          'I am an <b ng-show="test">invisible</b> HTML string with ' +
          '<a href="#" ' + $scope.dir + '="clicked()">links!</a> and other <em>stuff</em>';
      }
    ])

  // modified plunker taken from https://stackoverflow.com/questions/18063280/angularjs-inline-directives-with-ng-bind-html-unsafe
  //
  // Allows an attribute's value to be evaluated and compiled against the scope, resulting
  // in an angularized template being injected in its place.
  //
  // Note: This directive is prefixed with "unsafe" because it does not sanitize the HTML. It is up
  // to the developer to ensure that the HTML is safe to insert into the DOM.
  //
  // Usage:
  //     HTML: <div unsafe-bind-html="templateHtml"></div>
  //     JS: $scope.templateHtml = '<a ng-onclick="doSomething()">Click me!</a>';
  //     Result: DIV will contain an anchor that will call $scope.doSomething() when clicked.
  .directive('unsafeBindHtml', ['$compile',
    function($compile) {
      return function(scope, element, attrs) {
        scope.$watch(
          function(scope) {
            // watch the 'compile' expression for changes
            return scope.$eval(attrs.unsafeBindHtml);
          },
          function(value) {
            // when the 'compile' expression changes
            // assign it into the current DOM element
            element.html(value);

            // compile the new DOM and link it to the current
            // scope.
            // NOTE: we only compile .childNodes so that
            // we don't get into infinite loop compiling ourselves
            $compile(element.contents())(scope);
          }
        );
      };
    }
  ]);
<!doctype html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Example</title>


  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.5/angular.min.js"></script>
  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.5/angular-sanitize.js"></script>
  <script src="script.js"></script>



</head>

<body ng-app="bindHtmlExample">
  <div ng-controller="ExampleController">
    <p unsafe-bind-html="myHTML"></p>

    (click on the link to see <code>ng-click</code> in action)
  </div>
</body>

</html>

关于javascript - Angular 表达式选择一个指令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26269341/

相关文章:

javascript - AngularJS 应用程序模板中的 JS 插件不起作用

javascript - 在 Protractor 中验证测试结果(非 "expect"函数)

javascript - 使用两个不同的 Controller 文件时,部分 View ng-click 不起作用

javascript - 如何将对象的每个值放入数组中

javascript - event.target 和 getelementbyid 之间的区别

javascript - 退出先前操作中残留的按键事件

javascript - 正则表达式检测奇数个连续引号

javascript - 如何追加到 select2 中现有的下拉选项之一?

java - Angular.js 和 Java Applet

javascript - AngularJS 范围定义的函数为 null