如何在指令中观察和重新评估表达?

时间:2015-02-19 15:10:45

标签: angularjs angularjs-directive

我正在尝试编写自定义指令,其中一个要求是我应该能够根据指令属性上设置的表达式禁用其中一个元素。指令声明如下

<sr-payment-edit payment="vm.paymentInfo" disablepaymenttypeselection="!vm.isPolicySelected || someOtherCondition">

如果尚未选择政策,基本上应该隐藏付款类型。 选择策略后,将启用付款类型。这是指令

部分的html模板
<div class="row" data-ng-hide='hidePaymentType'>
    <div class="col-xs-12 p-l-0 p-r-0">
        <div class="col-xs-3">
            <div class="form-group">
                <label>Payment Type:</label>
                <select data-ng-model="payment.paymentTypeCode"
                        data-ng-disabled="disablePaymentType" class="form-control" style="width: 150px">
                    <option value="CASH">Cash</option>
                    <option value="CHCK">Check</option>
                    <option value="CCPP">Credit Card - Pre Pay</option>
                    <option value="MNOD">Money Order</option>
                </select>
            </div>
        </div>
    </div>
</div>

这是早期阶段的指令代码

(function (angular) {

    'use strict';

    angular.module('app').directive('srPaymentEdit', srPaymentEditDirectiveFactory);

    function srPaymentEditDirectiveFactory() {
        return {
            restrict: 'E',
            templateUrl: 'app/app_directives/sr-paymentEdit/sr-paymentEdit.html',
            scope: {
                payment: '=',
                disablepaymenttypeselection: '@',
                hidepaymenttypeselection: '@'
            },
            transclude: false,
            controller: controller,
            link: link
        };
    }

    function link($scope, element, attrs, model) {

        if (attrs.hidepaymenttypeselection) {
            $scope.hidePaymentType = $scope.$eval(attrs.hidepaymenttypeselection);

        }

        if (attrs.disablepaymenttypeselection) {

            $scope.$watch(attrs.disablepaymenttypeselection, function (value) {
                $scope.disablePaymentType = $scope.$eval(attrs.disablepaymenttypeselection);
            });

        }  
    }

    function controller($scope) {

        if ($scope.payment != null) {

            if ($scope.payment instanceof PaymentInfo === false) {
                throw 'Invalid datasource type, must be instance of PaymentInfo';
            }

        } else {
            var info = new PaymentInfo();
            info.paymentTypeCode = 'CHCK';
            $scope.payment = info;
        }
    }
})(angular);

到目前为止这么好,观看火灾并禁用选择,但在“vm.isPolicySelected”更改后,自然会注意属性不会触发。

是否可以触发监视以便重新评估“disablepaymenttypeselection”?

3 个答案:

答案 0 :(得分:0)

看起来问题是在指令范围配置中,您需要使用=绑定,而不是属性@。所以试试这个:

scope: {
    payment: '=',
    disablepaymenttypeselection: '=',
    hidepaymenttypeselection: '@'
},

并且稍微改变手表部分(仅使用属性名称):

$scope.$watch('disablepaymenttypeselection', function(value) {
    $scope.disablePaymentType = $scope.$eval(attrs.disablepaymenttypeselection);
});

答案 1 :(得分:0)

您声明您的属性&#39; disablepaymenttypeselection&#39;和&#39; hidepaymenttypeselection&#39;是一种文本绑定方式:

        scope: {
            payment: '=',
            disablepaymenttypeselection: '@',
            hidepaymenttypeselection: '@'
        },

我认为您需要使用双向绑定(&#39; =&#39;),这样您就可以切换(布尔值)属性来隐藏或显示您的HTML。

使用您的代码如果您使用console.log($ scope.disablepaymenttypeselection)&#39;,您将得到以下输出为字符串:

!vm.isPolicySelected || someOtherCondition

阅读本文以获取有关指令和绑定的更多信息:When writing a directive in AngularJS, how do I decide if I need no new scope, a new child scope, or a new isolated scope?

答案 2 :(得分:0)

搞定了。我的问题是我创建了一个独立的范围,但我想响应父范围的更改,而不显式传入所有依赖项。所以我重写了这样的指令

function srPaymentEditDirectiveFactory() {
    return {
        restrict: 'E',
        templateUrl: 'app/app_directives/sr-paymentEdit/sr-paymentEdit.html',
        scope: true,
        //scope: {
        //    vm:'=',
        //    payment: '=',
        //    disablepaymenttypeselection: '=',
        //    hidepaymenttypeselection: '@'
        //},
        transclude: false,
        //controller: controller,
        link: link
    };
}

function link($scope, element, attrs, model) {

    var info = null;

    if (attrs.payment == undefined) {
        info = new PaymentInfo();
        info.paymentTypeCode = 'CHCK';

    } else {
        info = $scope.$eval(attrs.payment);

        if (info instanceof PaymentInfo === false) {
            throw 'Invalid datasource type, must be instance of PaymentInfo';
        }
    }

    $scope.payment = info;

    if (attrs.hidepaymenttypeselection) {
            $scope.hidePaymentType = $scope.$eval(attrs.hidepaymenttypeselection);
        }

        if (attrs.disablepaymenttypeselection) {
            $scope.$watch(attrs.disablepaymenttypeselection, function (value) {
                $scope.disablePaymentType = $scope.$eval(attrs.disablepaymenttypeselection);
            });
        }
    }

})(angular);