35

DEMO

考虑以下指令:

angular.module('MyApp').directive('maybeLink', function() {
  return {
    replace: true,
    scope: {
      maybeLink: '=',
      maybeLinkText: '='
    },
    template: '<span>' + 
              '  <span ng-hide="maybeLink" ng-bind-html="text"></span>' +
              '  <a ng-show="maybeLink" href="#" ng-bind-html="text"></a>' +
              '</span>',
    controller: function($scope) {
      $scope.text = $scope.maybeLinkText.replace(/\n/g, '<br>');
    }
  }; 
});

该指令将 the<span>和 the添加<a>到 DOM(一次只有一个可见)。

我怎样才能重写指令,使其将添加到 DOM或添加<span><a>DOM,但不能同时添加?


更新

好的,我想我可以ng-if这样使用:

template: '<span>' + 
          '  <span ng-if="!maybeLink" ng-bind-html="text"></span>' +
          '  <a ng-if="maybeLink" href="#" ng-bind-html="text"></a>' +
          '</span>'

但是,在这种情况下,如何摆脱周围的环境<span>


更新 2

这是使用$compile. 它没有环境<span>,但双向数据绑定也不起作用。我真的很想知道如何解决双向数据绑定问题。有任何想法吗?

DEMO

angular.module('MyApp').directive('maybeLink', function($compile) {
  return {
    scope: {
      maybeLink: '=',
      maybeLinkText: '='
    },
    link: function(scope, element, attrs) {
      scope.text = scope.maybeLinkText.replace(/\n/g, '<br>');

      if (scope.maybeLink) {
        element.replaceWith($compile('<a href="#" ng-bind-html="text"></a>')(scope));
      } else {
        element.replaceWith($compile('<span ng-bind-html="text"></span>')(scope));  
      } 
    } 
  }; 
});
4

6 回答 6

43

您也许可以使用一个template 函数。根据文档

您可以将模板指定为表示模板的字符串,也可以指定为接受两个参数 tElement 和 tAttrs(在下面的编译函数 api 中描述)并返回表示模板的字符串值的函数


function resolveTemplate(tElement, tAttrs) {

}

angular.module('MyApp').directive('maybeLink', function() {
  return {
    //...
    template: resolveTemplate,
    //...
  }; 
});
于 2014-01-14T03:49:12.333 回答
32

我认为这是基于范围属性注入动态模板的最简洁方法

angular.module('app')
.directive('dynamic-template', function () {
  return {
    template:'<ng-include src="template"/>',
    restrict: 'E',
    link: function postLink(scope) {
      scope.template = 'views/dynamic-'+scope.type+'.html';
    }
  };
})
于 2014-12-01T12:34:53.453 回答
5

最后我想出了以下版本:

angular.module('MyApp').directive('maybeLink', function($compile) {
  return {
    scope: {
      maybeLink: '=',
      maybeLinkText: '='
    },
    link: function(scope, element, attrs) {
      scope.$watch('maybeLinkText', function(newText) {
        scope.text = newText.replace(/\n/g, '<br>');
      });

      scope.$watch('maybeLink', function() {
        var newElement;

        if (scope.maybeLink) {
          newElement = $compile('<a href="#" ng-bind-html="text"></a>')(scope);
        } else {
          newElement = $compile('<span ng-bind-html="text"></span>')(scope);
        }

        element.replaceWith(newElement); // Replace the DOM
        element = newElement;            // Replace the 'element' reference
      });
    }
  };
});
于 2013-09-19T13:47:21.427 回答
3

我会用ng-switch.

就像是

 template: '<span ng-switch on="maybeLink">' + 
          '  <span ng-switch-when="http://www.yahoo.com" ng-bind-html="text"></span>' +
          '  <a ng-switch-when="http://google.com" href="#" ng-bind-html="text"></a>' +
          '</span>',

或者

 template: '<span ng-switch on="maybeLink">' + 
          '  <span ng-switch-when={{maybeLink.length == 0}} ng-bind-html="text"></span>' +
          '  <a ng-switch-when={{maybeLink.length > 0}} href="#" ng-bind-html="text"></a>' +
          '</span>',

所以这是方向

Plunker

于 2013-09-19T11:09:05.593 回答
2

你也可以使用 ng-if

下面是工作示例

Working Demo

指令代码:

angular.module('MyApp').directive('maybeLink', function() {
  return {
    replace: true,
    scope: {
      maybeLink: '=',
      maybeLinkText: '='
    },
    template: '<span>' + 
              '  <span ng-if="!maybeLink.link" ng-bind-html="text"></span>' +
              '  <a ng-if="maybeLink.link" href="#" ng-bind-html="text"></a>' +
              '</span>',
    controller: function($scope) {
      $scope.text = $scope.maybeLinkText.replace(/\n/g, '<br>');
    }
  }; 
});
于 2013-09-19T11:16:51.157 回答
1

以下是提供动态更新的解决方案。用法:

<a rewrite-as-span="true"></a>

<a rewrite-as-span="false"></a>

<a rewrite-as-span="yourFn()"></a>

等等

app.directive('rewriteAsSpan', function($compile){
  return {
    restrict: 'A',
    template: '<span />',
    replace: true,

    // we transclude the element because when it gets replaced with the span
    // we want all the properties from the original element
    transclude: 'element',

    compile: function(tElement, tAttrs){

      return {
        post: function(scope, element, attrs, controller, transclude){
          var rewrittenEl, originalEl;

          transclude(scope, function(clone){
            originalEl = clone;
          });


          scope.$watch(attrs.rewriteAsSpan, function(value){
            if (value === undefined || value === true){
              if (!rewrittenEl){
                // lazy compile and cache the rewritten element
                transclude(scope, function(clone){
                  rewrittenEl = tElement;
                  rewrittenEl.html(clone.html());
                  // remove this directive because the $compile would get infinite
                  rewrittenEl.removeAttr('rewrite-as-span');
                  $compile(rewrittenEl)(scope);
                });

              }

              element.replaceWith(rewrittenEl);
              element = rewrittenEl;

            } else {
              element.replaceWith(originalEl);
              element = originalEl;
            }
          });

        }
      };
    }
  };
});

代码和规范作为要点

于 2014-02-05T00:01:23.143 回答