从指令中的attr角度保存监视表达式

时间:2015-03-09 14:19:48

标签: javascript angularjs

我想在指令中将一些html传递给attr,问题是我所做的不是保存绑定它只显示初始值,我怎么能在这里完成数据绑定?

function link( $scope, elem, attrs, ctrl, transclude ) {
    $scope.dropDownClass = attrs.ddClass || 'default';
    var main = $compile(attrs.main)($scope);
    elem.find('button').first().append(main);
  }

<my-drop-down main='<a><img src="images/flags/en.png" alt="en"/>{{name}}</a>'>
 <li><a><img src="images/flags/en.png" alt="en"/>En</a></li>
</my-drop-down>

我希望{{name}}仍然绑定到我的控制器。

http://plnkr.co/edit/IrF1dIZslCEQf0FOfNJi?p=preview

2 个答案:

答案 0 :(得分:1)

好的,我快速看一下。从我所看到的,在 attr查找之前,正在评估主要属性。因此,您实际上正在编译<a>World</a> 而不是 <a>{{name}}</a>

我认为没有办法告诉angular不要评估属性(标记有ngNonBindable,但这对我们没有帮助)。我看到了两个解决方案。

选项#1 :您可以从属性中提取所需的模板字符串,然后将其附加到MainCtrl中的范围。看起来像这样:http://plnkr.co/edit/M6GZJDVHuW8op2Zo11mJ?p=preview

// Markup:
<my-drop-down> ...

// MainCtrl:
app.controller('MainCtrl', function($scope) {
  $scope.name = 'World';
  $scope.main = '<a>{{name}}</a>';
});

// Then, in your directive link:
function link($scope, elem, attrs, ctrl, transclude ) {
  $scope.dropDownClass = attrs.ddClass || 'default';
  // Use scope.main, instead of attrs.main:
  var main = $compile($scope.main)($scope);
  elem.find('button').first().append(main);
}

选项#2 :如果你想保持模板字符串在属性中的传递我们不能,据我所知,使用花括号并期望它们以卷曲的方式传递括号。因此,我们可以尝试使用对我们的代码来说足够独特的其他东西。我选择%%,但它可能是你想要的任何东西,真的。这看起来像这样:http://plnkr.co/edit/760CFsq9sF9lIBHgO2Ic?p=preview

// Markup:
<my-drop-down main="<a>%%name%%</a>">

// Then, in your directive link:
function link($scope, elem, attrs, ctrl, transclude ) {
  $scope.dropDownClass = attrs.ddClass || 'default';
  // Replace our template string and compile that w/ braces:
  var tpl = attrs.main.replace(/%%([a-z]+)%%/g, '{{$1}}');
  var main = $compile(tpl)($scope);
  elem.find('button').first().append(main);
}

您可以采取其他选项,例如创建隔离范围等,但它们需要对代码进行更多重构。上面两个似乎是最容易接受的。

答案 1 :(得分:1)

问题是当你的链接功能被执行时,name已被插值。

除了@rgthree所说的你还可以使用compile函数on指令只调用var compiled = $compile(tAttrs.main),然后在链接函数中调用范围为var main = compiled($scope)的返回值:

compile: function compile(tElement, tAttrs, transclude) {
      var compiled = $compile(tAttrs.main);
      return function( $scope, elem, attrs, ctrl, transclude ) {
          $scope.dropDownClass = attrs.ddClass || 'default';
          console.log(3);
          var main = compiled($scope);
          elem.find('button').first().append(main);
      }
    },

选中此plunker