gpt4 book ai didi

angularjs - Angular 1.6 使用 $setValidity 自定义验证指令

转载 作者:行者123 更新时间:2023-12-02 22:59:50 25 4
gpt4 key购买 nike

我正在尝试编写一个自定义指令,用于根据指令中也需要提供的其他值来验证输入字段。我通过使用带有范围变量的隔离范围来做到这一点。更具体地说,我想将产品的客户价格(即其净价)与购买价格进行比较,如果差异为负(客户价格设置为 0 除外),我想让客户- 价格输入(及其周围形式)无效。这是我的指令:

export class CheckMarkupDirective implements ng.IDirective {
public static create(): ng.IDirective {
return {
restrict: "A",
require: "ngModel",
scope: {
netPrice: "<",
markupAmount: "<"
},
link: (scope: ng.IScope, element: ng.IAugmentedJQuery, attrs: ng.IAttributes, ngModelCtrl: ng.INgModelController) => {

let netPrice: number;
let markupAmount: number;
scope.$watchGroup(["netPrice", "markupAmount"], (newValues, oldValues) => {

[netPrice, markupAmount] = newValues;

if (markupAmount >= 0) {
ngModelCtrl.$setValidity("markup", true);
} else {
ngModelCtrl.$setValidity("markup", netPrice === 0);
}
ngModelCtrl.$validate();
});
}
};
}
}

这就是我在由表单标签包围的 ng-form div 中使用它的方式:

<input type="text" id="customer-price" name="customerPrice"
ng-model="ctrl.product.customerPrice"
ng-change="ctrl.customerPriceChangeDetected()"
check-markup markup-amount="ctrl.product.markupAmount"
net-price="ctrl.product.netPrice" />

它可以工作,但问题是验证部分似乎“计时错误”,这意味着如果我输入一个导致“标记”第一次变为负值的值,那么表单的 $invalid值设置为 false。但是,当接下来输入为负数时,验证将启动并起作用。我认为我的问题是我在不同步骤之间进行了大量计算,但我很难知道是什么导致验证如此失败。我想我希望有人对 Angular JS 机制有更深入的了解,并告诉我我是否做了一些明显错误的事情。提前致谢,如果我的描述有点含糊,抱歉。

编辑:我想还包括在 ng-change 上触发的方法:

public customerPriceChangeDetected(): void {
this.setNetPriceFromCustomerPrice();
this.setMarkup();
this.changeDetected();
}
private setNetPriceFromCustomerPrice(): void {
let customerPrice = this.product.customerPrice;
let vatRate = this.product.vatRate;
let netPrice = (customerPrice / (1 + vatRate));
this.product.netPrice = parseFloat(accounting.toFixed(netPrice, 2));
}
private setMarkup(): void {
let purchasePrice = this.product.purchasePrice;
let markupAmount = this.product.netPrice - purchasePrice;
this.product.markupAmount = markupAmount;
this.product.markupPercent = markupAmount / purchasePrice;
}
public changeDetected(): void {
let isValid = this.validationService ? this.validationService.isValid : false;
this.toggleSaveButton(isValid);
}

验证服务 getter 基本上返回 form.$valid 并且对于我所有其他自定义验证器来说工作得非常好。

编辑 2: 添加了屏幕截图,显示周围的 ng-form 标记似乎将其 $invalid 属性至少设置为 true: enter image description here

编辑3:这是转译后的 JS:

var CheckMarkupDirective = (function () {
function CheckMarkupDirective() {
}
CheckMarkupDirective.create = function () {
return {
restrict: "A",
require: "ngModel",
scope: {
netPrice: "<",
markupAmount: "<"
},
link: function (scope, element, attrs, ngModelCtrl) {
var netPrice;
var markupAmount;
scope.$watchGroup(["netPrice", "markupAmount"], function (newValues, oldValues) {
netPrice = newValues[0], markupAmount = newValues[1];
if (!markupAmount || !netPrice)
return;
if (markupAmount >= 0) {
ngModelCtrl.$setValidity("markup", true);
}
else {
ngModelCtrl.$setValidity("markup", netPrice === 0);
}
//ngModelCtrl.$validate();
});
}
};
};
return CheckMarkupDirective; }());

...这是我的 html 的精简版本:

<form autocomplete="off" class="form-horizontal" role="form" name="productDetailsForm" novalidate data-ng-init="ctrl.setForm(this,'productDetailsForm')">
<div data-ng-form="section2">
<div class="form-group">
<label for="purchase-price" class="col-sm-4 control-label">Purchase price</label>
<div class="col-sm-4">
<input type="text" class="form-control" id="purchase-price" name="purchasePrice"
data-ng-model="ctrl.product.purchasePrice"
data-ng-change="ctrl.purchasePriceChangeDetected();"
data-decimal="Currency" />
</div>
</div>
<div class="form-group">
<label for="vat-rate" class="col-sm-4 control-label">VAT rate</label>
<div class="col-sm-4">
<select class="form-control" id="vat-rate"
data-ng-model="ctrl.product.vatRate"
data-ng-change="ctrl.vatRateChangeDetected()"
data-ng-options="vatRate.value as vatRate.text for vatRate in ctrl.vatRates"></select>
</div>
</div>
<div class="form-group" data-has-error-feedback="productDetailsForm.section2.customerPrice">
<label for="customer-price" class="col-sm-4 control-label">Customer price</label>
<div class="col-sm-4">
<input type="text" class="form-control" id="customer-price" name="customerPrice"
data-ng-model="ctrl.product.customerPrice"
data-ng-change="ctrl.customerPriceChangeDetected();"
data-decimal="Currency"
data-check-markup
data-markup-amount="ctrl.product.markupAmount"
data-net-price="ctrl.product.netPrice" />
<invalid-feedback item="productDetailsForm.section2.customerPrice"></invalid-feedback>
<validation-feedback type="markup" item="productDetailsForm.section2.customerPrice" data-l10n-bind="ADMINISTRATION.PRODUCTS.NET_PRICE.INVALID"></validation-feedback>
</div>
<div class="col-sm-4">
<div class="form-group" style="margin-bottom: 0;">
<label for="net-price" class="col-lg-5 col-md-5 col-sm-5 col-xs-5" style="font-weight: normal; margin-top: 7px;">
<span data-l10n-bind="ADMINISTRATION.PRODUCTS.NET_PRICE"></span>
</label>
<label class="col-lg-7 col-md-7 col-sm-7 col-xs-7" style="font-weight: normal; margin-top: 7px;">
<span id="net-price">{{ ctrl.product.netPrice | currency }}</span>
</label>
</div>
</div>
</div>
<div class="form-group" data-has-error-feedback="productDetailsForm.section2.markup">
<label for="markup-amount" class="col-sm-4 col-xs-4 control-label">Markup</label>
<div class="col-sm-8 col-xs-8">
<label id="markup-percent" class="control-label" data-ng-class="{'text-danger': ctrl.product.markupPercent < 0}">
{{ ctrl.product.markupPercent * 100 | number: 2 }}%
</label>
<label id="markup-amount" class="control-label" data-ng-class="{'text-danger': ctrl.product.markupAmount < 0}">
({{ ctrl.product.markupAmount | currency }})
</label>
</div>
</div>
</div>

我已在指令中的 watch 内放置了断点,由于某些奇怪的原因,当我第一次在客户价格输入中输入新值时, watch 似乎没有触发。相反,我发现自己直接进入了changeDetected()方法。我现在真的很困惑。我认为这个问题与验证之前触发的 ng-change 指令有关。我可能有一个错误的逻辑,导致在指令有时间实际改变有效性之前触发我的验证服务的 isValid 检查。

最佳答案

尝试删除隔离范围并直接评估属性:

export class CheckMarkupDirective implements ng.IDirective {
public static create(): ng.IDirective {
return {
restrict: "A",
require: "ngModel",
/* REMOVE isolate scope
scope: {
netPrice: "<",
markupAmount: "<"
},
*/
link: (scope: ng.IScope, element: ng.IAugmentedJQuery, attrs: ng.IAttributes, ngModelCtrl: ng.INgModelController) => {

let netPrice: number;
let markupAmount: number;
//scope.$watchGroup(["netPrice", "markupAmount"],
//WATCH attributes directly
scope.$watchGroup([attrs.netPrice, attrs.markupAmount], (newValues, oldValues) => {

[netPrice, markupAmount] = newValues;

if (markupAmount >= 0) {
ngModelCtrl.$setValidity("markup", true);
} else {
ngModelCtrl.$setValidity("markup", netPrice === 0);
}
ngModelCtrl.$validate();
});
}
};
}
}

inputng-modelng-change 指令需要一个没有作用域的元素。这消除了一次性绑定(bind)观察者以及隔离范围对抗这些指令的复杂性。

关于angularjs - Angular 1.6 使用 $setValidity 自定义验证指令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41323893/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com