在范围变量更改后重新计算传递给指令的属性

Re-evaluate attributes passed to directive after scope variable changes

本文关键字:计算 属性 指令 变量 范围 新计算      更新时间:2023-09-26

我在ng-repeat中生成了一系列元素:

<tr ng-repeat="index in elements">
  <td ng-click="doSomething(index)" my-tooltip tooltip="isInBasket(index.id) && 'REMOVE FROM BASKET' || 'ADD TO BASKET'" ></td>
</tr>

指令 MyTooltip 需要传递给 tooltip 属性的值。
这将在第一次工作,这意味着当执行 ng-repeat 时。如果元素已在购物篮中,则工具提示的值将为"从购物篮中删除",否则值为"添加到购物篮"。

该函数定义如下:

$scope.isInBasket = (id){
  return _.contains($scope.basket, id)
}

现在,我的代码的其他部分将更改$scope.basket,因此我认为每当$scope.basket更改时都会重新评估isInBasket,从而更改传递给tooltip属性的值。

该指令

angular.module("tooltips", [])
    .directive("myTooltip", ($parse, $rootScope, $state){
      return {  
        restrict: 'A',
        priority: 999,
        link: function(scope, elm, attrs) {
          tooltip = scope.$eval(attrs.tooltip);
          // .... 
        }
      }
    })

但这不起作用,我很确定我做错了什么,或者我错过了什么。

您是否正在创建一个独立作用域?,如果是,则需要在作用域中声明:{工具提示:"&"}

我认为问题在于您绑定到布尔值,因为不可变会破坏双重绑定,但老实说,不确定您如何执行工具提示指令

尝试使用您的指令:

angular.module("tooltips", [])
  .directive("myTooltip", ($parse, $rootScope, $state){
    return { 
      scope: { tooltip: "=" } //you could try also "&"
      restrict: 'A',
      priority: 999    
    }
})

好的,如果您尝试分配如下值:

var tooltip = {dock: scope.$eval(attrs.tooltip)};

或 var tooltip = element.scope()[attrs.tootip];

我的意思是我知道在绑定中对对象进行绑定非常重要。

如果这没有帮助,您可以将其与手表绑定,那应该这样做:

link: function(scope, elm, attrs) {
  var tooltip = element.scope()[attrs.tootip];
  scope.$watch(function () {
    return scope.attrs.tooltip; // i dont know what changes in your app
  }, function() {
    return  tooltip();
  }, true);

使用tooltip="{{isInBasket(index.id) && 'REMOVE FROM BASKET' || 'ADD TO BASKET'}}"

请看下文

var app = angular.module('plunker', ['ui.bootstrap']);
app.controller('MainCtrl', function($scope) {
  $scope.name = 'World';
  $scope.elements = [{
    id: 0,
    name: "banana"
  }, {
    id: 1,
    name: "pear"
  }, {
    id: 2,
    name: "apple"
  }]
  $scope.basket = [];
  $scope.basket.push($scope.elements[0].id)
  $scope.isInBasket = function(id) {
    return _.contains($scope.basket, id)
  }
  $scope.doSomething = function(item) {
    if (_.contains($scope.basket, item.id)) {
      $scope.basket = _.without($scope.basket, item.id)
    } else {
      $scope.basket.push(item.id)
    }
  }
});
tr {
  border: 1px solid grey;
}
<html ng-app="plunker">
<head>
  <meta charset="utf-8" />
  <title>AngularJS Plunker</title>
  <link data-require="bootstrap-css@3.1.*" data-semver="3.1.1" rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" />
  <script>
    document.write('<base href="' + document.location + '" />');
  </script>
  <link rel="stylesheet" href="style.css" />
  <script data-require="angular.js@1.2.x" src="https://code.angularjs.org/1.2.25/angular.js" data-semver="1.2.25"></script>
  <script data-require="ui-bootstrap@*" data-semver="0.12.0" src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.12.0.min.js"></script>
  <script data-require="lo-dash@*" data-semver="2.4.1" src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.js"></script>
  <script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
  <h1>Hello {{name}}!</h1>
  Basket : {{basket | json }}
  <div class="container">
    <table>
      <tbody>
        <tr ng-repeat="index in elements">
          <td ng-click="doSomething(index)" tooltip="{{isInBasket(index.id) && 'REMOVE FROM BASKET' || 'ADD TO BASKET'}}" style="padding-left:150px">
            {{index.id}}
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</body>
</html>