5

我正在尝试创建一个具有“正在加载”状态的可重用按钮指令。也就是说,当单击它时,它会禁用自身并显示一个内联图像以表示加载,然后在完成时将其删除。我通过在 click 方法中设置范围变量并取消设置它来完成此操作,这会更改按钮的状态。

我希望它在单击时调用的方法位于父范围内,并且我还希望它挂钩到父范围的验证中,因此当父表单无效时它会自行禁用。这些是我难以开始工作的部分——我知道我的问题与范围有关,但我被困住了。

<loading-button class="login" data-ng-click="login()" text="Login" toggle="loaded"></loading-button>

我希望做类似下面的事情,但是如何绑定在指令实例上声明的 click 方法以从指令中实际调用?或者,这是不好的做法吗?这目前不起作用。

angular.module("App.directives").directive("loadingButton", function () {
return {
    restrict: "E",
    replace: true,
    transclude: true,
    template: '<button data-ng-click="{{ngClick}}">{{text}}<img class="loading" src="images/ButtonLoader.gif" alt=""></button>',
    scope: {
        "toggle": "=",
        "text": "=",
        "ng-disabled": "=",
        "disabled": "=",
        "ngClick": "&"
    },
    link: function(scope, element, attributes) {
        scope.text = attributes.text;
        var expression = attributes.toggle;

        scope.$watch(expression, function(newValue, oldValue) {
            if(newValue === oldValue) {
                return;
            }

            if(newValue) {
                element.removeAttr("disabled");
                element.find("img.loading").hide();
            }
            else {
                element.attr("disabled", "disabled");
                element.find("img.loading").show();
            }
        });
    }
  };
});

在父作用域中像这样使用:

$scope.login = function () {
    $scope.loaded = false;  // Disable button and show it loading

    // Do login stuff

    $scope.loaded = true; // Enable button and hide it loading
}

编辑:

这是一个小提琴

http://jsfiddle.net/jonathanwest/frvk6/2/

4

1 回答 1

1

编辑- 最简单的解决方案:如果您所做的只是启用一个按钮并隐藏该按钮中的元素,那么您根本不需要指令:

<button ng-click="login()" ng-disabled="loading"><img ng-show="loading">Login</button>

否则,如果您希望在指令中使用它:

对于初学者,您不需要{{}}在模板中的点击声明中,您需要调用().

我正在将属性引用从 ngClick 更改为 click - angular 不喜欢您使用其名称作为属性:

<button data-ng-click="click()">

并将ng-showandng-disabled用于您的按钮和图像。

<button ng-click="click()" ng-disabled="text==\'loading\'">
    <img ng-show="text==\'loading\'">{{text}}</button>

.

对于text属性,由于您只是读取字符串的值,因此您需要将该范围设置更改为text: "@".

此外,由于toggle在您的隔离范围内设置,您可以$watch直接进行更改。

*请注意,这只是基于范围禁用和显示元素的示例$watch。您的禁用和显示可能需要与以下值完全相反的值,或者可能取决于不同的范围变量:

scope.$watch('toggle', function(newValue, oldValue) {
            if(newValue === oldValue) {
                return;
            }

            if(newValue) {
                scope.text = "loaded";
               ;
            }
            else {
                scope.text="loading";

            }
        });

.

这个小提琴反映了一个基于您的设置的工作示例,使用$timeout.

于 2013-07-11T14:46:24.530 回答