【问题标题】:Run AngularJS directive on demand按需运行 AngularJS 指令
【发布时间】:2015-07-17 09:00:24
【问题描述】:

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

  .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 变量的任何变化。但我没有实现让它工作,指令只在加载时运行。

有什么方法可以按需运行指令吗?因为我的指令正在加载,但是当 scope 改变时没有。

提前谢谢你!

编辑

这就是问题的外观。左表是右:第 3、4 和 8 行包含文件,因此它启用了下载按钮。 但是右表呈现错误的这个按钮,因为 directive 不再运行。它的正确值是启用的第 12、14 行。

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

【问题讨论】:

  • 尝试使用指令作为类或属性,然后动态添加类或属性...
  • 指令不能被“调用”。它们是您网站的静态部分。如果要有条件地显示指令,请使用ng-show/ng-hide。如果您想有条件地从 DOM 中添加或删除指令,请使用 ng-if/ng-switch。我认为您以错误的方式解决问题-指令不应在其链接函数中进行$http 调用。

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


【解决方案1】:

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

  • 不是函数
  • 无法调用
  • 是您网站的静态部分,除非您使用 ng-if 或 ng-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 可能看起来像这样:

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

【讨论】:

  • 好的,我向你公开我的目标:我有一些可以附加文件的东西的列表。知道它的方法是调用 Rest-service,如果响应长度超过 30(我不知道为什么 30,是服务器响应),则附加了一些东西。一旦您知道是否包含文件,我想启用下载按钮(如果有),或者禁用(如果没有文件)。
  • 那么我认为您应该使用类似于我建议的方法,但根据需要进行更改以满足您的需求。
  • 是的,我试一试,到时候我会喂你的。谢谢,丹!
  • 不走运,你的问题是在控制器中调用$scope.row.entity.id,因为它不知道正在显示哪些行。这是一个场景:一个有 20 行的表,每页分页 5 行。控制器知道有 20 行,指令只看到 5。它适用于这 5 个初始行,但不适用于以下。 :(
猜你喜欢
  • 2014-03-20
  • 1970-01-01
  • 2021-11-21
  • 1970-01-01
  • 2014-04-30
  • 2015-08-24
  • 1970-01-01
  • 1970-01-01
  • 2019-10-04
相关资源
最近更新 更多