从指令动态添加Angular属性到元素

16
我正在尝试构建一个指令,用于在处理缓慢的ajax调用时更改按钮的加载状态。基本上,想法是将一个属性"ng-loading"设置为按钮元素,并让指令添加其余的内容。
这是HTML代码:
<button class="btn btn-primary" name="commit" type="submit" ng-loading="signupLoading">
  Submit
</button>

这是指令代码:

.directive('ngLoading', ['$compile',  function($compile) {
  return {
    restrict: 'A',
    replace: false,
    terminal: true,
    link: function(scope, element, attrs) {
      element.attr('ng-class', '{loading:' + attrs['ngLoading'] +'}');
      element.attr('ng-disabled', attrs['ngLoading']);
      element.append(angular.element('<img class="loading-icon" src="/assets/images/loading-icon.gif"/>'));
      $compile(element.contents())(scope);
    }
  };
}]);

在渲染的HTML中看起来都是正确的,但是从指令中添加的属性根本没有起作用。我可以将这些属性移动到HTML代码中,然后一切都能正常工作,但这在许多地方会造成冗余代码。

我参考了这篇文章[译]Angular指令:为现有DOM元素动态设置属性,但它没有解决我的问题。

欢迎任何评论/建议。提前致谢。

1个回答

25

如果你只需要进行一些DOM操作,而不是重新编译指令,那么可以根据作用域属性的变化添加和删除类。你可以使用 $watch 来实现。

JAVASCRIPT

.directive('ngLoading', function() {
  return function(scope, element, attrs) {
    var img = angular.element('<img class="loading-icon" src="/assets/images/loading-icon.gif"/>');
    element.append(img);
    scope.$watch(attrs.ngLoading, function(isLoading) {
       if(isLoading) {
         img.removeClass('ng-hide');
         element.addClass('loading');
         element.attr('disabled', '');
       } else {
         img.addClass('ng-hide');
         element.removeClass('loading');
         element.removeAttr('disabled');
       }
    });
  };
});

注意:你的代码无法正常工作,因为它编译了元素的内容而不是元素本身,在这里您可以添加实现的属性。

尝试使用$compile(elem)(scope);,它应该可以正常工作,但我不推荐这样做,因为每个带有这种指令的元素都需要重新编译。

更新:在使用$compile之前,请将'ngLoading'属性从元素中删除,以防止无限编译。

elem.removeAttr('ng-loading');
$compile(elem)(scope);

谢谢你的回答。这应该解决了我的问题。虽然我仍然想知道为什么我的代码不起作用。 - johnw
请检查我的更新,如果你想知道为什么我们的代码不起作用。 - ryeballar
谢谢你的帮助。我尝试了$compile(elem)(scope);但它仍然不起作用。它一直导致我的浏览器(Chrome)崩溃。 - johnw
非常感谢。这真的很有帮助。 - johnw

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接