Angular.js: لم يتم استدعاء وظيفة ngModelController $ بشكل متناسق

تم إنشاؤها على ١٠ أغسطس ٢٠١٥  ·  3تعليقات  ·  مصدر: angular/angular.js

عند فرض قيم الإدخال لتتوافق مع قواعد معينة باستخدام دالة محلل 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 (على الرغم من أنه يقوم بتحديث قيمة العنصر) ، مما يؤدي إلى سلوك غير متوقع.

يتم توضيح هذا بشكل أفضل بمثال:

  1. يقوم المستخدم بإدخال "1".

    • _قبل_ الاعراب:



      • $modelValue : غير محدد


      • $viewValue : 1


      • element.val() : 1



    • _After_ الاعراب:



      • $modelValue : 1


      • $viewValue : 1


      • element.val() : 1



  2. يقوم المستخدم بإدخال "x".

    • _قبل_ الاعراب:



      • $modelValue : 1


      • $viewValue : 1x


      • element.val() : 1x



    • _After_ الاعراب:



      • $modelValue : 1


      • $viewValue : 1x (لم يتم التحديث مطلقًا من المحلل اللغوي fn)


      • element.val() : 1 (تم التحديث من المحلل اللغوي fn)



  3. يقوم المستخدم بإدخال "x".

    • _قبل_ الاعراب:



      • $modelValue : 1


      • $viewValue : 1x (لم يتم الكشف عن أي تغيير ، حيث أن $viewValue كان أيضًا 1x )


      • element.val() : 1x



    • _No_ التحليل (حيث لم يتم الكشف عن أي تغيير في $viewValue ) !!!



      • $modelValue : 1


      • $viewValue : 1x


      • element.val() : 1x



  4. يقوم المستخدم بإدخال "x".

    • _قبل_ الاعراب:



      • $modelValue : 1


      • $viewValue : 1xx


      • element.val() : 1xx



    • _After_ الاعراب:



      • $modelValue : 1


      • $viewValue : 1xx


      • element.val() : 1



  5. _ (... رجوع إلى الخطوة (2) ...) _

هناك عدة طرق "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 ، لا تتردد في المتابعة بأسئلة إذا كان أي شيء غير واضح.

ال 3 كومينتر

يستخدم $parsers لتحويل (نسخة من) $viewValue قبل "حفظه" كـ $modelValue (وهذا ما يفعله مثالك). إنه لا يغير في الواقع $viewValue (على الرغم من أنه يقوم بتحديث قيمة العنصر) ، مما يؤدي إلى سلوك غير متوقع.

يتم توضيح هذا بشكل أفضل بمثال:

  1. يقوم المستخدم بإدخال "1".

    • _قبل_ الاعراب:



      • $modelValue : غير محدد


      • $viewValue : 1


      • element.val() : 1



    • _After_ الاعراب:



      • $modelValue : 1


      • $viewValue : 1


      • element.val() : 1



  2. يقوم المستخدم بإدخال "x".

    • _قبل_ الاعراب:



      • $modelValue : 1


      • $viewValue : 1x


      • element.val() : 1x



    • _After_ الاعراب:



      • $modelValue : 1


      • $viewValue : 1x (لم يتم التحديث مطلقًا من المحلل اللغوي fn)


      • element.val() : 1 (تم التحديث من المحلل اللغوي fn)



  3. يقوم المستخدم بإدخال "x".

    • _قبل_ الاعراب:



      • $modelValue : 1


      • $viewValue : 1x (لم يتم الكشف عن أي تغيير ، حيث أن $viewValue كان أيضًا 1x )


      • element.val() : 1x



    • _No_ التحليل (حيث لم يتم الكشف عن أي تغيير في $viewValue ) !!!



      • $modelValue : 1


      • $viewValue : 1x


      • element.val() : 1x



  4. يقوم المستخدم بإدخال "x".

    • _قبل_ الاعراب:



      • $modelValue : 1


      • $viewValue : 1xx


      • element.val() : 1xx



    • _After_ الاعراب:



      • $modelValue : 1


      • $viewValue : 1xx


      • element.val() : 1



  5. _ (... رجوع إلى الخطوة (2) ...) _

هناك عدة طرق "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:

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات