按需运行AngularJS指令

时间:2015-07-17 09:00:24

标签: javascript angularjs angularjs-directive angular-ui-grid

我尝试在某些事件后运行指令,例如,某些点击或模型更改。以下是我的指令的外观:

  .directive('enclose', function ($window, $http) {
      return function (scope, elm, attrs) {
          if (scope.$last) {
              var url = getCurrentPath($window);
              var rowid = scope.row.entity.id;
              $http.get(url + '/' + rowid + '/attachment').success(function (data) {
                  (data.length > 30) ? $(elm).removeAttr('disabled') : $(elm).attr('disabled', 'disabled');
              })
          }
  };

长话短说:指令检查一行是否附加了文件;如果是这样,它启用下载按钮。

在该表中,显示数据,有很多行,并且它具有分页控件。因此,当我点击下一页(f.e.)时出现问题,表中显示的所有数据都会更新,但指令不会。我的意思是,指令不再运行,更新每个按钮的启用/禁用属性。

我有两种方法:一种,在我的控制器中我有一个范围变量, currentPage ,在更新之后,我以某种方式调用该指令。顺便说一下,我使用 Angular UI-grid 来渲染数据。

  $scope.regulationGrid = {
          // ...
          onRegisterApi: function (gridApi) {
              $scope.gridApi = gridApi;
              $scope.currentPage = $scope.gridApi.pagination.getPage();
              $scope.gridApi.pagination.on.paginationChanged($scope, function () {
                  $scope.currentPage = $scope.gridApi.pagination.getPage();
                  // Here should be the directive call
              });
          }
      };

二,在指令中使用 $ watch 函数,该函数将监听 $ scope currentPage 变量中的任何更改。但是我没有实现它的工作,指令只能在加载时运行。

有没有办法运行按需指令?因为我的指令正在加载,但是当范围更改时没有。

提前谢谢!

修改

enter image description here 这是看起来如何的问题。左表是右:第3行,第4行和第3行第8个包含文件,它启用下载按钮。 但是右表使这个按钮出错,因为指令不再运行。它的正确值是第12,第14行启用。

所以重点是,在点击nextPage按钮后如何检查这些值?

1 个答案:

答案 0 :(得分:0)

正如我在评论中提到的,指令:

  • 不是功能
  • 无法调用
  • 是您网站的静态部分,除非您使用ng-ifng-switch
  • 不应执行任何业务逻辑

看来你的问题是一个XY问题,所以让我们重新开始吧。你想做什么?

从它的外观来看,您希望根据HTTP调用的结果将指令设置为禁用或启用。如何在指令内部执行HTTP调用,而不是从隔离范围传递指令并从父控制器更改该变量?这使您的代码更少耦合,并让您遵守最佳角度实践。

// usage: <enclose disabled="someScopeVariable"></enclose>
.directive('enclose', function() {
  return {
    scope: {
      value: '=',
      // One time binding is only supported natively in 1.3+.
      maxLength: '::'
    },
    link: function ($scope, $elem, $attrs) {
      var maxLength = parseInt($scope.maxLength);
      // What purpose does $scope.$last serve here?
      if(!$scope.$last) return;
      $scope.$watch('value', function(newValue, oldValue) {
        if(newValue === oldValue) {
          return;
        }

        if(oldValue.length > maxLength) {
          $elem.removeAttribute('disabled');
        } else {
          $elem.setAttribute('disabled', 'disabled');
        }
      });
    }
  }
})
.controller('YourController', function($scope, attachmentService) {
  $scope.regulationGrid = {
    onRegisterApi: function(gridApi) {
      .....
      $scope.gridApi.pagination.on.paginationChanged($scope, function() {
        $scope.currentPage = $scope.gridApi.pagination.getPage();
        // $http call is moved to external service.
        attachmentService.get($scope.row.entity.id)
          .then(function(data) {
            $scope.enclosedData = data;
          });
      });
    }
  };

})
.service('attachmentService', function() {
  this.get = function get(rowId) {
    // Why are you using getCurrentPath, by the way? That seems very hacky.
    // An alternative would be to use /api and then use a http interceptor to
    // rewrite /api to wherever the base path actually is. Either way,
    // the service shouldn't do this because of code duplication.
    return $http.get('/api/' + rowId + '/attachment').then(function(response) {
      return response.data;
    });
  };
});

然后你的html MIGHT看起来像这样:

<div ng-controller='YourController'>
  <enclose value="enclosedData" max-length="30">
  </enclose>
</div>