如何通过自定义Angular指令有条件地应用模板?

Mis*_*hko 35 angularjs angularjs-directive

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>');
    }
  }; 
});
Run Code Online (Sandbox Code Playgroud)

该指令将DOM <span><a>DOM 添加到DOM中(一次只能看到一个).

我怎么能改写指令,使其将增加或者<span><a>到DOM,但不能两者兼而有之?


UPDATE

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

template: '<span>' + 
          '  <span ng-if="!maybeLink" ng-bind-html="text"></span>' +
          '  <a ng-if="maybeLink" href="#" ng-bind-html="text"></a>' +
          '</span>'
Run Code Online (Sandbox Code Playgroud)

但是,<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));  
      } 
    } 
  }; 
});
Run Code Online (Sandbox Code Playgroud)

Lam*_*bda 43

您可以使用某个template 功能.根据文件:

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


function resolveTemplate(tElement, tAttrs) {

}

angular.module('MyApp').directive('maybeLink', function() {
  return {
    //...
    template: resolveTemplate,
    //...
  }; 
});
Run Code Online (Sandbox Code Playgroud)

  • 这是最干净的解决方案.我喜欢.当然,只要你不需要访问`scope`. (2认同)

yoh*_*sen 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';
    }
  };
})
Run Code Online (Sandbox Code Playgroud)


Mis*_*hko 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
      });
    }
  };
});
Run Code Online (Sandbox Code Playgroud)


Max*_*tin 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>',
Run Code Online (Sandbox Code Playgroud)

或者

 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>',
Run Code Online (Sandbox Code Playgroud)

所以这就是方向

Plunker