Angular指令,指模板内的元素内容

时间:2014-11-07 19:55:54

标签: javascript angularjs

我正在尝试制作一个指令,如果角度表达式为非空,则有条件地添加换行符。到目前为止,我有这个:

// this will show text with a <br> conditionally if the text is non-blank
angular.module('myApp.directives').directive('brIf', function () {
    return {
        scope: {
            text: '='
        },
        template: '<span ng-show="text && text.trim().length">{{ text }}<br/></span>'
    };
});

如果我这样使用它(地址的任何部分可能是未定义的或空白的),哪个有效:

<br-if text="address.number + ' ' + address.street + ' ' + address.apt"></br-if>

但我真正想要的是一个我可以这样使用的指令:

<!-- put a br at the end of all this jazz, only if the expression is not blank -->
<br-if>{{address.number}} {{address.street}} {{address.apt}}</br-if>

...避免所有字符串数学和text =属性。我知道我可以在我的指令中编写一个链接函数,通过元素参数获取html内容(我认为?),但我不知道如何在模板中使用该元素的内容。换句话说,请在链接功能中查看我的问题...

// this will show text with a <br> conditionally if the text is non-blank
angular.module('myApp.directives').directive('brIf', function () {
    return {
        scope: {
            text: '='
        },
        link: function(scope, elm, attrs, ctrl) {
            // I want the text of elm here to be used instead of 'text' 
            // in my template below.  Is this possible?
        },
        template: '<span ng-show="text && text.trim().length">{{ text }}<br/></span>'
    };
});

2 个答案:

答案 0 :(得分:5)

您可以使用transclusion

app.directive('brIf', function($interpolate) {
  return {
    restrict: 'E',
    template: '<span ng-show="text && text.trim().length">{{ text }}<br/></span>',
    transclude: true,
    link: function(scope, element, attrs, controller, transclusionFn) {

      transclusionFn(scope, function(clone) {

        scope.text = $interpolate(clone[0].innerHTML)(scope);
      });
    }
  };
});

你所追求的是clone,它将是你的被抄送内容的全新编译副本。这意味着例如clone[0].innerHTML将是:

{{address.number}} {{address.street}} {{address.apt}}

然后,您可以使用$interpolate服务将字符串编译为插值函数,使用此函数计算针对范围的插值字符串并使用结果:

var interpolationFn = $interpolate(clone[0].innerHTML);
var interpolatedString = interpolationFn(scope);
scope.text = interpolatedString;

或者简单地说:

scope.text = $interpolate(clone[0].innerHTML)(scope);

演示: http://plnkr.co/edit/VNauZ0Kkr1HLCnsWTgyO?p=preview

答案 1 :(得分:2)

对于大多数情况,您不需要完整transclusionFn。如果您在指令选项中设置transclude: true,则只需将ng-transclude添加到您希望添加内容的模板中:

<div class="example" style="background: blue; height: 30px; width: 30px" ng-transclude></div>

参考:https://stackoverflow.com/a/16697788/175830