2013-06-02 29 views
5

Tôi đã tạo một chỉ thị xác nhận cho biểu mẫu của mình. Về cơ bản nó xác nhận giá trị trường dựa trên dữ liệu từ trường khác.Làm cách nào để buộc chỉ thị xác thực góc chạy?

Nó hoạt động hoàn hảo :-)

Vấn đề của tôi là nếu trường khác thay đổi sau khi xác thực được thực hiện, xác thực sẽ không chạy lại.

var myApp = angular.module('myApp', []) 

.directive('validateInteger', function() { 
    return { 
    require: 'ngModel', 
    link: function(scope, elm, attrs, ctrl) { 
     ctrl.$parsers.unshift(function(viewValue) { 
      var int1val = scope.int1; 
      scope.int2valid = (viewValue > int1val) ? "valid" : undefined; 
      if (scope.int2valid == "valid") { 
       ctrl.$setValidity('higher', true); 
       return viewValue; 
      } else { 
       ctrl.$setValidity('higher', false); 
       return undefined; 
     } 
     }); 
    } 
    }; 
}); 

jsfiddle: http://jsfiddle.net/hanspc/vCFFQ/

+0

Điều này sẽ không khắc phục sự cố "xác thực", nhưng bạn có thể ẩn div bằng 'ng-hide =" int2> int1 "', đặt toán tử '>' ngay trong biểu thức ẩn. – rGil

Trả lời

3

Đó là một ý tưởng thực sự xấu để tham khảo một cách rõ ràng đối với một số lĩnh vực trong Chỉ thị của bạn. Như bạn có thể thấy, đây có rất nhiều nhược điểm: unportability, mã lặp lại, giòn, ...

Chỉ cần chắc cái gì đó như thế:

<input type="text" ng-model="int2" validate-greater-integer="int1" /> 

Và:

myApp.directive('validateGreaterInteger', function() { 
    return { 
    require: 'ngModel', 
    scope: { 
     otherInteger : '=validateGreaterInteger', 
    } 
    link: function(scope, elm, attrs, ctrl) { 
     ctrl.$parsers.unshift(function(viewValue) { 
     if (viewValue > scope.otherInteger) { 
      ctrl.$setValidity('higher', true); 
      return viewValue; 
     } else { 
      ctrl.$setValidity('higher', false); 
      return undefined; 
     } 
    } 
}); 

Bạn có thể sau đó chỉ cần làm the typical state control (xem phần "Ràng buộc để tạo thành và kiểm soát trạng thái" cho một ví dụ).

Xin lưu ý rằng, trong trường hợp này, bạn cũng có thể chỉ cần sử dụng input[number] và thông số min của nó.


Chỉnh sửa sau khi các cuộc thảo luận trong ý kiến:

Vâng, các chức năng trong NgModelController.$parsers rõ ràng là được gọi là chỉ khi nội dung của những thay đổi mô hình. Những gì bạn muốn làm là xác thực bất cứ khi nào int1 hoặc int2 thay đổi. Vì vậy, chỉ cần làm điều đó :-):

link: function(scope, elm, attrs, ctrl) { 
    scope.$watch('data', function (data) { 
     if (data.int2 > data.int1) { 
      ctrl.$setValidity('higher', true); 
      return data.int2; 
     } else { 
      ctrl.$setValidity('higher', false); 
      return undefined; 
    } 
    }, true); 

Sử dụng biến xác thực của riêng bạn (int2valid trong Fiddle) cũng rất lạ. Vui lòng sử dụng the typical state control, với một cái gì đó như form.int2.$error.higher.

+0

Tôi biết những hạn chế - đây chỉ là một ví dụ đơn giản của chỉ thị xác nhận của tôi :-) Xác nhận kiểm tra số nguyên cho một số thứ (min, max, một số phép tính dựa trên các trường khác v.v.) Và khi các trường khác được thay đổi bởi người dùng, tôi cần xác thực để chạy lại. Tôi đã cố gắng sử dụng chức năng phạm vi thay thế (được gọi bằng ng-thay đổi trên các trường khác), nhưng tôi không thể quản lý để sử dụng hàm $ setValidity từ phạm vi - tôi nhận được: 'Object # has không có phương thức '$ setValidity'' – hansch

+0

Đề xuất của tôi không giải quyết được vấn đề? Tóm lại: chỉ cần sử dụng nhiều tham số khi cần thiết trong chỉ thị của bạn, liên kết chúng với '' 'scope''' cục bộ và thực hiện tất cả phép tính của bạn trong' '' unshift''', như tôi làm trong ví dụ của tôi. – Blackhole

+0

Không thực sự, bởi vì việc xác thực không biết liệu giá trị khác có thay đổi hay không. Xem http://jsfiddle.net/hanspc/vCFFQ/4/ Chèn 2 vào Int1 và 3 vào Int2. Sau đó thay đổi Int1 thành 5, và Int2 vẫn hợp lệ mặc dù nó thực sự không phải là :-) – hansch

2

Có thể một giải pháp đơn giản hơn sẽ là với người quan sát hoặc thậm chí là một biểu thức bên trong phần mở đầu ng-show của khoảng thời gian lỗi của bạn.

Sử dụng một biểu thức bên trong chỉ thị ng-show sẽ là như thế này:

<span ng-show="int1 > int2" style="color: red; display:none"> 

Nếu không, bạn có thể xem các thay đổi trong mô hình INT1 và int2 và so sánh giá trị của họ:

$scope.$watch('int1+int2', function() { 
    if($scope.int1 > $scope.int2) { 
     $scope.error = true;  
    }else { 
     $scope.error = false; 
    } 
}) 

<span ng-show="error" style="color: red; display:none"> 

đây là một fiddle

+2

giải pháp tuyệt vời trong trường hợp bạn đang tìm kiếm một số quy tắc xác thực rất phức tạp và quy tắc đó chỉ được yêu cầu trên một trang duy nhất – coure2011

Các vấn đề liên quan