عند فرض قيم الإدخال لتتوافق مع قواعد معينة باستخدام دالة محلل ngModelController $ ، لا يتم استدعاء وظيفة محلل $ عند ضغطات المفاتيح المتكررة "غير الصالحة" ، مما يسمح بإضافة أحرف غير صالحة.
في المثال أدناه ، يهدف التوجيه إلى إزالة جميع الأحرف غير الرقمية. يعمل في الغالب ، ولكن إذا قمت بكتابة نفس الحرف غير الرقمي مرتين على التوالي (على سبيل المثال "xx") ، فسيظهر "x" واحد في الإدخال. إذا قمت بكتابة "x" للمرة الثالثة ، فسيتم حذف "x".
لقد قمت أيضًا بتضمين حالة اختبار فاشلة.
كل التعليمات البرمجية تعمل على http://codepen.io/visnup/pen/YXgLVq؟
استخدام التوجيه
<div ng-app="digits">
<input ng-model="number" placeholder="digits only" digits-only />
</div>
التوجيه
angular
.module('digits', [])
.directive('digitsOnly', function() {
return {
require: 'ngModel',
link: function link(scope, element, attrs, ngModel) {
ngModel.$parsers.push(function(value) {
var numbers = value.replace(/\D/g, '');
element.val(numbers);
return numbers;
});
}
};
});
حالة الاختبار الفاشلة
describe('digits', function() {
beforeEach(angular.mock.module('digits'));
let scope, input;
beforeEach(inject(function($compile, $rootScope) {
scope = $rootScope;
input = $compile('<input ng-model="number" digits-only />')(scope);
}));
// works
it('should block non-digits', function() {
input.val('111x');
input.triggerHandler('input');
expect(input.val()).to.equal('111');
});
// doesn't work
it('should not flash incorrect input', function() {
input.val('111x');
input.triggerHandler('input');
input.val('111x');
input.triggerHandler('input');
expect(input.val()).to.equal('111');
});
});
تم طرح هذا من قبل في # 10700.
يستخدم $parsers
لتحويل (نسخة من) $viewValue
قبل "حفظه" كـ $modelValue
(وهذا ما يفعله مثالك). إنه لا يغير في الواقع $viewValue
(على الرغم من أنه يقوم بتحديث قيمة العنصر) ، مما يؤدي إلى سلوك غير متوقع.
يتم توضيح هذا بشكل أفضل بمثال:
$modelValue
: غير محدد$viewValue
: 1element.val()
: 1$modelValue
: 1$viewValue
: 1element.val()
: 1$modelValue
: 1$viewValue
: 1xelement.val()
: 1x$modelValue
: 1$viewValue
: 1x (لم يتم التحديث مطلقًا من المحلل اللغوي fn)element.val()
: 1 (تم التحديث من المحلل اللغوي fn)$modelValue
: 1$viewValue
: 1x (لم يتم الكشف عن أي تغيير ، حيث أن $viewValue
كان أيضًا 1x
)element.val()
: 1x$viewValue
) !!!$modelValue
: 1$viewValue
: 1xelement.val()
: 1x$modelValue
: 1$viewValue
: 1xxelement.val()
: 1xx$modelValue
: 1$viewValue
: 1xxelement.val()
: 1هناك عدة طرق "Angular" للتعامل مع هذا الأمر بشكل صحيح ، على سبيل المثال:
ngModel.$parsers.push(function (value) {
var numbers = value.replace(/\D/g, '');
if (numbers !== value) {
ngModel.$setViewValue(numbers); // Update the `$viewValue`
ngModel.$render(); // Update the element's displayed value
}
return numbers;
});
أقوم بإغلاق هذا ، حيث يبدو أن كل شيء يعمل كما هو متوقع.
visnup ، لا تتردد في المتابعة بأسئلة إذا كان أي شيء غير واضح.
تحدث هذه المشكلة مع تكرار ضغطات المفاتيح في أي وقت لا يتم فيه تنفيذ $ viewValue الجديد. يتم أحيانًا تجنب الاستخدام المقترح لـ $ setViewValue في مجموعة المحللون $ مع تفضيل تعيين $ viewValue مباشرةً في بعض المنتديات.
يعمل ما يلي أيضًا:
ngModel.$viewValue = numbers; // Update the '$viewValue'
ngModel.$commitViewValue(); //update $$lastCommittedViewValue
ngModel.$render(); // Update the element's displayed value
إذا كنت ترغب في تجنب أي مخاطر عودية على الإطلاق ، فيمكن تحديث $$ lastCommittedViewValue مباشرةً إذا كنت لا تمانع في انتهاك الكبسولة. لسوء الحظ ، عندما تحدث العودية اللانهائية في هذه الوظائف ، رأيت حالات لم يتم إبلاغ وحدة التحكم فيها حتى بعد الحد الأقصى من الحدوث. من الجدير أخذ بضع دقائق لوضع نقطة فاصل أثناء الاختبار والتحقق من أي تكرارات.
تفسيراتgkalpak و snaptech مجتمعة تشكل حلاً ذهبيًا :): +1:
التعليق الأكثر فائدة
يستخدم
$parsers
لتحويل (نسخة من)$viewValue
قبل "حفظه" كـ$modelValue
(وهذا ما يفعله مثالك). إنه لا يغير في الواقع$viewValue
(على الرغم من أنه يقوم بتحديث قيمة العنصر) ، مما يؤدي إلى سلوك غير متوقع.يتم توضيح هذا بشكل أفضل بمثال:
$modelValue
: غير محدد$viewValue
: 1element.val()
: 1$modelValue
: 1$viewValue
: 1element.val()
: 1$modelValue
: 1$viewValue
: 1xelement.val()
: 1x$modelValue
: 1$viewValue
: 1x (لم يتم التحديث مطلقًا من المحلل اللغوي fn)element.val()
: 1 (تم التحديث من المحلل اللغوي fn)$modelValue
: 1$viewValue
: 1x (لم يتم الكشف عن أي تغيير ، حيث أن$viewValue
كان أيضًا1x
)element.val()
: 1x$viewValue
) !!!$modelValue
: 1$viewValue
: 1xelement.val()
: 1x$modelValue
: 1$viewValue
: 1xxelement.val()
: 1xx$modelValue
: 1$viewValue
: 1xxelement.val()
: 1هناك عدة طرق "Angular" للتعامل مع هذا الأمر بشكل صحيح ، على سبيل المثال:
قلم محدث
أقوم بإغلاق هذا ، حيث يبدو أن كل شيء يعمل كما هو متوقع.
visnup ، لا تتردد في المتابعة بأسئلة إذا كان أي شيء غير واضح.