$formatter を含むいくつかのカスタム検証コードがあります。(正確を期すために通貨をペンスで保存しますが、ポンド.ペンスで表示します。)
ユーザーが入力に '10' を入力した場合 (これは有効な値です)、次のフィールドに移動した後も入力には '10' が表示されたままになります。
一貫性を保つために 10.00 を表示したいと思います。
モデルが値を 1000 に変更した場合、フォーマッタはフィールドに「10.00」を表示します。
フォーマッタを field.blur() で実行したいと思います (入力が有効である限り)。
私の問題は、モデル値を 10 から 10 に変更すると、当然のことながら変更がないため、フィールドが再レンダリングされないことです。
コード:
var CURRENCY_REGEXP = /^\-?\d+(\.?\d?\d?)?$/;
app.directive('currency', function() {
return {
require: 'ngModel',
link: function(scope, elm, attrs, ctrl) {
ctrl.$parsers.unshift(function(viewValue) {
if (CURRENCY_REGEXP.test(viewValue)) {
// it is valid
ctrl.$setValidity('currency', true);
console.log("valid");
return viewValue * 100;
} else if (viewValue === '') {
return 0;
} else {
// it is invalid, return undefined (no model update)
ctrl.$setValidity('currency', false);
console.log("invalid");
return undefined;
}
});
ctrl.$formatters.push(function(modelValue) {
if (modelValue === 0) { // we're using integer pence, so this is safe
return '';
}
return (modelValue / 100).toFixed(2);
});
}
};
});
PS これは、Angular の組み込みの「通貨」とは何の関係もありません。
更新: Andy の回答に従って、「renderOnBlur」ディレクティブを追加しました。呼び出されますが、render メソッドを呼び出しても入力は再レンダリングされません。つまり、'10' は、必要に応じて '10.00' に変更するのではなく、'10' のままです。
(これらのフィールドでモデル値が変更されると、小数点以下 2 桁で正しくレンダリングされます。)
Andy が言及しているページhttp://docs.angularjs.org/api/ng.directive:ngModel.NgModelControllerには、自分で実装する必要があると書かれてい$render
ます。モデル値が変更されたときに入力がすでに正しくレンダリングされているため、これは奇妙に思えます。
app.directive('renderOnBlur', function() {
return {
require: 'ngModel',
restrict: 'A',
link: function(scope, elm, attrs, ctrl) {
elm.bind('blur', function() {
console.log('rendering ctrl', ctrl);
ctrl.$render();
});
}
};
});
PS私は何が何をするのか分かりrestrict: 'A',
ません-それは最悪の真のカーゴカルトプログラミングです. パラメータrequire: 'ngModel',
を入力する必要があるようです。ctrl
@Dan Doyen からの回答に触発されて、次のように書き直しました。
app.directive('renderOnBlur', function() {
return {
require: 'ngModel',
restrict: 'A',
link: function(scope, elm, attrs, ctrl) {
elm.bind('blur', function() {
var viewValue = ctrl.$modelValue;
for (var i in ctrl.$formatters) {
viewValue = ctrl.$formatters[i](viewValue);
}
ctrl.$viewValue = viewValue;
ctrl.$render();
});
}
};
});
これには、ダンの回答のようにフォーマッタ コードを繰り返すのではなく、任意の $formatter に対して汎用的であるという利点があります。