我有一个自定义验证指令iban
,用于检查该值是否为有效(荷兰语)IBAN。该验证器需要将值大写。我还有一个uppercase
指令,它将值更改为大写。我想在一个输入元素上组合两个:
<input type="text" ng-model="iban" name="iban" capitalize="" iban="" />
我创建了jsfiddle来证明这种情况。
我正在努力处理正确的执行顺序。如果用户键入一个值,我想首先触发大写,因此iban验证器会收到一个大写的值。如果模型值是从代码设置的,我也想先将其大写。
当用户键入小写字符时,大写指令调用ctrl。$ setViewValue来设置视图值。这会触发解析器的另一次运行。因此,大写指令和iban指令都执行了两次。控制台日志显示:
parsers.capitalize: nL12HHBA0429672071
uppercasing: nL12HHBA0429672071 => NL12HHBA0429672071, setting view value
parsers.capitalize: NL12HHBA0429672071
uppercasing: NL12HHBA0429672071 already uppercased
parsers.iban: NL12HHBA0429672071
setting validity to: true
returning NL12HHBA0429672071
parsers.iban: NL12HHBA0429672071
setting validity to: true
returning NL12HHBA0429672071
我认为不打算多次遍历解析器。
另一个问题是当我将代码中的值设置为已经大写的无效IBAN时(我小提琴中的最后一个链接)。在这种情况下,大写指令不必执行任何操作。 iban指令格式化程序将有效性设置为false,并返回该值。如果它是小写无效的IBAN,则大写指令将调用setViewValue,从而导致IBAN指令解析器代码执行,这将返回undefined
。这样情况会将模型的值更改为undefined。
我是不是太复杂了?我是否应该尝试创建一个iban指令,以确保当用户输入有效的小写iban值时,大写的值会存储在模型中?如果从代码设置,我应该只保留模型中的小写值吗?也许只需在元素上使用style="text-transform: uppercase"
来始终显示值,就像它是大写的一样?缺点是如果将模型设置为有效但较低的值,则表单将显示大写的值,该值有效,而模型值实际上无效。
答案 0 :(得分:1)
这里肯定有些复杂。在玩弄时,也有一些角度怪异(至少在我眼里 - 我会达到这个目的)。
此处介绍的一个复杂因素是您的capitalize
$formatter
实际上更改了模型值。我认为这违背了格式化程序函数的意图(转换model -> view
方向的值)。视图(以及格式化程序通过其指令位于视图中)应仅在更改源自视图时更改模型。这使得模型成为事实的来源,如果它被设置为无效值,那么就是这样 - 有效性应该反映在视图中,但它不应该试图“修复”模型。
考虑到这一点,我们还使用$validators
进行验证(而不是$ parsers / $ formatters管道):
.directive("iban", function(){
return {
require: "?ngModel",
link: function(scope, element, attrs, ngModel){
if (!ngModel) return;
ngModel.$validators.iban = function(modelValue, viewValue){
// after parser ran, validate the resulting modelValue
return validate(modelValue);
};
function validate(val){
return modelValue === "VALID IBAN"; // for the sake of example
}
}
};
});
$parsers
(更改模型值)和$formatters
(更改视图值)在$validators
运行之前调用。
另一个复杂性(以及看似Angular的奇怪之处)是,capitalize
格式化程序可以使$viewValue
对无效$modelValue
有效。这本身就行为正确 - 它格式化$viewValue
并将有效性保持为假(因为模型是假的)。但是,如果您现在将模型更改为当前设置(且有效)$viewValue
,则Angular决定跳过(src)验证器(因为它发现新旧{{1}之间没有区别尽管模型和视图值都是有效的,但有效性永远不会变得有效。同样,对于有效无效的情况(无效的低案例值永远不会使模型无效)。
然而,这是一种罕见的情况,如果应该完全避免编码。为什么?因为模型很少(如果有的话)假设无效值并且应该在有效范围内运行。
$viewValues
通过将模型设置为ng-model
来获取无效值,从而确保这一点(默认情况下,除非您allowInvalid
)。
因此,对于您的问题,请确定在您定义的ViewModel中,小写IBAN是否被视为无效: