Angular.js: ngModelController $parsers ν•¨μˆ˜κ°€ μΌκ΄€λ˜κ²Œ ν˜ΈμΆœλ˜μ§€ μ•ŠμŒ

에 λ§Œλ“  2015λ…„ 08μ›” 10일  Β·  3μ½”λ©˜νŠΈ  Β·  좜처: angular/angular.js

ngModelController $parser ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ νŠΉμ • κ·œμΉ™μ„ μ€€μˆ˜ν•˜λ„λ‘ μž…λ ₯ 값을 μ μš©ν•  λ•Œ $parser ν•¨μˆ˜λŠ” 반볡적인 "잘λͺ»λœ" ν‚€ μž…λ ₯에 λŒ€ν•΄ ν˜ΈμΆœλ˜μ§€ μ•ŠμœΌλ―€λ‘œ 잘λͺ»λœ λ¬Έμžκ°€ 좔가될 수 μžˆμŠ΅λ‹ˆλ‹€.

μ•„λž˜ μ˜ˆμ—μ„œ μ§€μ‹œλ¬Έμ€ μˆ«μžκ°€ μ•„λ‹Œ λͺ¨λ“  문자λ₯Ό μ œκ±°ν•˜κΈ° μœ„ν•œ κ²ƒμž…λ‹ˆλ‹€. λŒ€λΆ€λΆ„ μž‘λ™ν•˜μ§€λ§Œ λ™μΌν•œ μˆ«μžκ°€ μ•„λ‹Œ 문자λ₯Ό μ—°μ†μœΌλ‘œ 두 번 μž…λ ₯ν•˜λ©΄(예: 'xx') 단일 'x'κ°€ μž…λ ₯에 ν‘œμ‹œλ©λ‹ˆλ‹€. 'x'λ₯Ό μ„Έ 번째 μž…λ ₯ν•˜λ©΄ 'x'κ°€ μ œκ±°λ©λ‹ˆλ‹€.

λ‚˜λŠ” λ˜ν•œ μ‹€νŒ¨ν•œ ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€λ₯Ό ν¬ν•¨μ‹œμΌ°λ‹€.

λͺ¨λ“  μ½”λ“œλŠ” http://codepen.io/visnup/pen/YXgLVq?editors=101 μ—μ„œ μ‹€ν–‰ μ€‘μž…λ‹ˆλ‹€

μ§€μ‹œμ–΄ μ‚¬μš©

<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)둜 λŒμ•„κ°€κΈ°...)_

이λ₯Ό μ μ ˆν•˜κ²Œ μ²˜λ¦¬ν•˜λŠ” λͺ‡ 가지 "각도" 방법이 μžˆμŠ΅λ‹ˆλ‹€. 예:

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)둜 λŒμ•„κ°€κΈ°...)_

이λ₯Ό μ μ ˆν•˜κ²Œ μ²˜λ¦¬ν•˜λŠ” λͺ‡ 가지 "각도" 방법이 μžˆμŠ΅λ‹ˆλ‹€. 예:

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κ°€ μ»€λ°‹λ˜μ§€ μ•Šμ„ λ•Œλ§ˆλ‹€ ν‚€ μž…λ ₯을 λ°˜λ³΅ν•  λ•Œ λ°œμƒν•©λ‹ˆλ‹€. $parsers μ»¬λ ‰μ…˜μ—μ„œ μ œμ•ˆλœ $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 λ“±κΈ‰