Kích hoạt xác thực tất cả các trường trong gửi Biểu mẫu Angular


81

Tôi đang sử dụng phương pháp này: http://plnkr.co/edit/A6gvyoXbBd2kfToPmiiA?p=preview để chỉ xác thực các trường bị mờ. Điều này hoạt động tốt, nhưng tôi cũng muốn xác thực chúng (và do đó hiển thị lỗi cho các trường đó nếu có) khi người dùng nhấp vào nút 'gửi' (không phải là gửi thực sự mà là một lệnh gọi dữ liệu-ng-click đến một hàm)

Có cách nào để kích hoạt xác thực lại tất cả các trường khi nhấp vào nút đó không?


Nút ở đâu trong plunkr?
callmekatootie

xin lỗi, plunker là những gì tôi có trụ sở mã của tôi on..I làm một ngã ba giống với hoàn cảnh của tôi chặt chẽ hơn: plnkr.co/edit/VfvCSmjlzpIgUH4go2Jn?p=preview
Maarten

Câu trả lời:


44

Điều phù hợp với tôi là sử dụng $setSubmittedhàm, hàm này lần đầu tiên hiển thị trong tài liệu góc ở phiên bản 1.3.20.

Trong trường hợp nhấp chuột mà tôi muốn kích hoạt xác thực, tôi đã làm như sau:

vm.triggerSubmit = function() {
    vm.homeForm.$setSubmitted();
    ...
}

Đó là tất cả những gì nó cần cho tôi. Theo tài liệu, nó "Đặt biểu mẫu về trạng thái đã gửi." Nó được đề cập ở đây .


4
điều này không hoạt động khi bạn đang sử dụng ng-messagesvà chỉ hiển thị chúng khi $ error && $ dirty .
JobaDiniz

@JobaDiniz Bạn đã thử hàm $ setDirty chưa? Nó cũng được đề cập trong liên kết từ câu trả lời của tôi: code.angularjs.org/1.3.20/docs/api/ng/type/form.FormController Hy vọng điều đó sẽ hữu ích!
phát triển

2
nó không hoạt động cho form... Tôi đã phải lặp lại tất cả các đầu vào và gọi $setDirty()chúng.
JobaDiniz

43

Tôi biết, đã hơi muộn để trả lời, nhưng tất cả những gì bạn cần làm là, buộc tất cả các hình thức bẩn. Hãy xem đoạn mã sau:

angular.forEach($scope.myForm.$error.required, function(field) {
    field.$setDirty();
});

và sau đó bạn có thể kiểm tra xem biểu mẫu của mình có hợp lệ hay không bằng cách sử dụng:

if($scope.myForm.$valid) {
    //Do something
}   

và cuối cùng, tôi đoán, bạn sẽ muốn thay đổi lộ trình của mình nếu mọi thứ có vẻ ổn:

$location.path('/somePath');

Chỉnh sửa : biểu mẫu sẽ không tự đăng ký trên phạm vi cho đến khi sự kiện gửi được kích hoạt. Chỉ cần sử dụng chỉ thị ng-submit để gọi một hàm, và gói phần trên trong hàm đó, và nó sẽ hoạt động.


1
bạn có thể cung cấp ví dụ về ng-submitchỉ thị kích hoạt theo chương trình không?
chovy

@chovy ng-submitchỉ liên kết một hàm với sự kiện gửi, tại sao không chỉ gọi hàm đó?
Thilak Rao

tôi có một chỉ thị được nhúng trong biểu mẫu để cập nhật trường biểu mẫu bên ngoài chỉ thị .... trình xác thực không được áp dụng trừ khi tôi nhấp và làm mờ trường biểu mẫu mà tôi muốn xác thực.
chovy

tôi sẽ không có đối tượng biểu mẫu được chuyển đến nó
chovy

@chovy Tôi không hiểu bạn đúng. Nhưng hãy để tôi cố gắng giúp bạn. Bạn đã thử xác thực về sự mất đi chưa?
Thilak Rao

17

Trong trường hợp ai đó quay lại điều này sau đó ... Không có cách nào ở trên phù hợp với tôi. Vì vậy, tôi đã tìm hiểu sâu hơn về xác thực dạng góc và tìm thấy hàm mà họ gọi để thực thi trình xác thực trên một trường nhất định. Thuộc tính này được gọi một cách thuận tiện $validate.

Nếu bạn có một biểu mẫu đã đặt tên myForm, bạn có thể gọi theo chương trình myForm.my_field.$validate()để thực hiện xác thực trường. Ví dụ:

<div ng-form name="myForm">
    <input required name="my_field" type="text" ng-blur="myForm.my_field.$validate()">
</div>

Lưu ý rằng việc gọi $validatecó ý nghĩa đối với mô hình của bạn. Từ tài liệu góc cho ngModelCtrl. $ Validate:

Chạy từng trình xác thực đã đăng ký (trình xác thực đồng bộ đầu tiên và sau đó là trình xác thực không đồng bộ). Nếu hiệu lực thay đổi thành không hợp lệ, mô hình sẽ được đặt thành không xác định, trừ khi ngModelOptions.allowInvalid là true. Nếu hiệu lực thay đổi thành hợp lệ, nó sẽ đặt mô hình thành $ modelValue hợp lệ có sẵn cuối cùng, tức là giá trị được phân tích cú pháp cuối cùng hoặc giá trị cuối cùng được đặt từ phạm vi.

Vì vậy, nếu bạn đang lên kế hoạch làm điều gì đó với giá trị mô hình không hợp lệ (như gửi một thông báo cho họ biết như vậy), thì bạn cần đảm bảo rằng giá trị allowInvalidnày được đặt truecho mô hình của bạn.


allowInvalidcó thể đọc thêm thảo luận về kết quả rất đáng ngạc nhiên "mô hình trở thành không xác định" nếu không có tại đây: github.com/angular/angular.js/issues/10035
pestophagous

12

Bạn có thể sử dụng Angular-Validator để làm những gì bạn muốn. Thật ngu ngốc khi sử dụng.

Nó sẽ:

  • Chỉ xác thực các trường trên $dirtyhoặc trênsubmit
  • Ngăn không cho biểu mẫu được gửi nếu nó không hợp lệ
  • Hiển thị thông báo lỗi tùy chỉnh sau khi trường $dirtyhoặc biểu mẫu được gửi

Xem bản demo

Thí dụ

<form angular-validator 
       angular-validator-submit="myFunction(myBeautifulForm)"
       name="myBeautifulForm">
       <!-- form fields here -->
    <button type="submit">Submit</button>
</form>

Nếu trường không vượt qua validatorthì người dùng sẽ không thể gửi biểu mẫu.

Kiểm tra các trường hợp sử dụng và ví dụ về angle-validator để biết thêm thông tin.

Tuyên bố từ chối trách nhiệm: Tôi là tác giả của Angular-Validator


11

Chà, cách góc cạnh là để nó xử lý xác thực, - vì nó thực hiện ở mọi thay đổi mô hình - và chỉ hiển thị kết quả cho người dùng, khi bạn muốn.

Trong trường hợp này, bạn quyết định thời điểm hiển thị lỗi, bạn chỉ cần đặt cờ: http://plnkr.co/edit/0NNCpQKhbLTYMZaxMQ9l?p=preview

Theo như tôi biết, có một vấn đề được gửi đến góc độ để cho phép chúng tôi kiểm soát biểu mẫu nâng cao hơn. Vì nó không được giải quyết, tôi sẽ sử dụng điều này thay vì phát minh lại tất cả các phương pháp xác nhận hiện có.

chỉnh sửa: Nhưng nếu bạn kiên quyết theo cách của mình, đây là bước sửa đổi của bạn với việc xác nhận trước khi gửi. http://plnkr.co/edit/Xfr7X6JXPhY9lFL3hnOw?p=preview Bộ điều khiển phát sự kiện khi nút được nhấp và lệnh thực hiện phép xác thực.


Điều này hoạt động trong ví dụ này, nhưng điều gì sẽ xảy ra nếu tôi, như tôi gặp trong trường hợp của tôi (nhưng không phải trong plunkr đó..xin lỗi!), Thì một chỉ thị giống như email đó. Bằng cách nào đó, tôi có phải di chuyển xác thực ra khỏi các chỉ thị vào một lớp xác thực riêng biệt và sau đó gọi tất cả các phương thức xác thực của biểu mẫu này hay bằng cách nào đó tôi có thể kích hoạt xác thực theo cách khác cho tất cả các chỉ thị. Vì quá trình xác thực được kích hoạt bằng cách làm mờ, thậm chí có thể kích hoạt làm mờ từ mã, nhưng điều đó có vẻ kinh khủng.
Maarten

Ồ và tôi biết về vấn đề này. Thật không may, nó vẫn chưa ở phiên bản beta và quy trình làm việc mà tôi đang nói đến là quy trình bắt buộc đối với công ty này
Maarten

Sự kiện được phát sóng sẽ kích hoạt lệnh gọi lại $ on trong mọi chỉ thị vì tất cả chúng đều thuộc phạm vi của bộ điều khiển.
Oliver

ahh..không thực sự hiểu phần đó. Cảm ơn!
Maarten

1
Khi bạn phát sóng sự kiện, bạn có thể chuyển các tham số. $ scope. $ broadcast ('startValidations', param1, param2); Việc lắng nghe vẫn không thay đổi: scope. $ On ('startValidations', validateMe); Và trong callback fn: function validateMe (event, param1, param2) {} Xem tài liệu: docs.angularjs.org/api/ng.$rootScope.Scope#$broadcast
Oliver

9

Một cách tiếp cận là buộc tất cả các thuộc tính trở nên bẩn. Bạn có thể làm điều đó trong mỗi bộ điều khiển, nhưng nó rất lộn xộn. Sẽ tốt hơn nếu có một giải pháp chung.

Cách dễ nhất mà tôi có thể nghĩ ra là sử dụng một chỉ thị

  • nó sẽ xử lý thuộc tính gửi biểu mẫu
  • nó lặp lại qua tất cả các trường biểu mẫu và đánh dấu các trường nguyên sơ là bẩn
  • nó kiểm tra xem biểu mẫu có hợp lệ không trước khi gọi hàm gửi

Đây là chỉ thị

myModule.directive('submit', function() {
  return {
    restrict: 'A',
    link: function(scope, formElement, attrs) {
      var form;
      form = scope[attrs.name];
      return formElement.bind('submit', function() {
        angular.forEach(form, function(field, name) {
          if (typeof name === 'string' && !name.match('^[\$]')) {
            if (field.$pristine) {
              return field.$setViewValue(field.$value);
            }
          }
        });
        if (form.$valid) {
          return scope.$apply(attrs.submit);
        }
      });
    }
  };
});

Và cập nhật html biểu mẫu của bạn, ví dụ:

 <form ng-submit='justDoIt()'>

trở thành:

 <form name='myForm' novalidate submit='justDoIt()'>

Xem ví dụ đầy đủ tại đây: http://plunker.co/edit/QVbisEK2WEbORTAWL7Gu?p=preview


4

Đây là chức năng toàn cục của tôi để hiển thị thông báo lỗi biểu mẫu.

 function show_validation_erros(form_error_object) {
        angular.forEach(form_error_object, function (objArrayFields, errorName) {
            angular.forEach(objArrayFields, function (objArrayField, key) {
                objArrayField.$setDirty();
            });
        });
    };

Và trong bất kỳ bộ điều khiển nào của tôi,

if ($scope.form_add_sale.$invalid) { 
    $scope.global.show_validation_erros($scope.form_add_sale.$error);
}

1
Điều này không trả lời câu hỏi.
Rafael Herscovici

Tôi đã thay đổi câu trả lời của mình. Vui lòng kiểm tra nó ngay bây giờ
Namal

2

Dựa trên câu trả lời của Thilak, tôi đã có thể đưa ra giải pháp này ...

Vì các trường biểu mẫu của tôi chỉ hiển thị thông báo xác thực nếu một trường không hợp lệ và đã được người dùng chạm vào nên tôi có thể sử dụng mã này được kích hoạt bởi một nút để hiển thị các trường không hợp lệ của tôi:

// Show/trigger any validation errors for this step
angular.forEach(vm.rfiForm.stepTwo.$error, function(error) {
  angular.forEach(error, function(field) {
    field.$setTouched();
  });
});
// Prevent user from going to next step if current step is invalid
if (!vm.rfiForm.stepTwo.$valid) {
  isValid = false;
}
<!-- form field -->
<div class="form-group" ng-class="{ 'has-error': rfi.rfiForm.stepTwo.Parent_Suffix__c.$touched && rfi.rfiForm.stepTwo.Parent_Suffix__c.$invalid }">

  <!-- field label -->
  <label class="control-label">Suffix</label>
  <!-- end field label -->
  <!-- field input -->
  <select name="Parent_Suffix__c" class="form-control"
          ng-options="item.value as item.label for item in rfi.contact.Parent_Suffixes"
          ng-model="rfi.contact.Parent_Suffix__c" />
  <!-- end field input -->
  <!-- field help -->
  <span class="help-block" ng-messages="rfi.rfiForm.stepTwo.Parent_Suffix__c.$error" ng-show="rfi.rfiForm.stepTwo.Parent_Suffix__c.$touched">
    <span ng-message="required">this field is required</span>
  </span>  
  <!-- end field help -->
</div>
<!-- end form field -->


2

Lưu ý: Tôi biết đây là một bản hack, nhưng nó rất hữu ích cho Angular 1.2 trở về trước mà không cung cấp một cơ chế đơn giản.

Việc xác thực bắt đầu với sự kiện thay đổi , vì vậy một số thứ như thay đổi giá trị theo chương trình sẽ không kích hoạt sự kiện đó. Nhưng kích hoạt sự kiện thay đổi sẽ kích hoạt xác thực. Ví dụ, với jQuery:

$('#formField1, #formField2').trigger('change');

Cách tiếp cận này là đơn giản. Thêm vào đó, nó có lợi thế là nó hoạt động trên (tất cả) các phiên bản Angular cũ hơn.
Paul LeBeau

3
Không phải angular way.
Rafael Herscovici

1

Để xác thực tất cả các trường của biểu mẫu khi tôi muốn, tôi thực hiện xác thực trên từng trường điều khiển $$ như sau:

angular.forEach($scope.myform.$$controls, function (field) {
    field.$validate();
});

0

Tôi thích cách tiếp cận này trong việc xử lý xác thực khi nhấp vào nút.

  1. Không cần gọi bất cứ thứ gì từ bộ điều khiển,

  2. tất cả đều được xử lý bằng một chỉ thị.

trên github


0

Bạn có thể thử điều này:

// The controller

$scope.submitForm = function(form){
   		//Force the field validation
   		angular.forEach(form, function(obj){
   			if(angular.isObject(obj) && angular.isDefined(obj.$setDirty))
   			{ 
   				obj.$setDirty();
   			}
   		})
        
        if (form.$valid){
		
			$scope.myResource.$save(function(data){
		     	//....
			});
		}
}
<!-- FORM -->

  <form name="myForm"  role="form" novalidate="novalidate">
<!-- FORM GROUP to field 1 -->
  <div class="form-group" ng-class="{ 'has-error' : myForm.field1.$invalid && myForm.field1.$dirty }">
      <label for="field1">My field 1</label>
        <span class="nullable"> 
        <select name="field1" ng-model="myresource.field1" ng-options="list.id as list.name for list in listofall"
          class="form-control input-sm" required>
            <option value="">Select One</option>
        </select>
        </span>
        <div ng-if="myForm.field1.$dirty" ng-messages="myForm.field1.$error" ng-messages-include="mymessages"></div>
  </div>
    
<!-- FORM GROUP to field 2 -->
  <div class="form-group" ng-class="{ 'has-error' : myForm.field2.$invalid && myForm.field2.$dirty }">
    <label class="control-label labelsmall" for="field2">field2</label> 
      <input name="field2" min="1" placeholder="" ng-model="myresource.field2" type="number" 
      class="form-control input-sm" required>
    <div ng-if="myForm.field2.$dirty" ng-messages="myForm.field2.$error" ng-messages-include="mymessages"></div>
  </div>

  </form>

<!-- ... -->
<button type="submit" ng-click="submitForm(myForm)">Send</button>


0

Tôi đã làm điều gì đó sau đây để làm cho nó hoạt động.

<form name="form" name="plantRegistrationForm">
  <div ng-class="{ 'has-error': (form.$submitted || form.headerName.$touched) && form.headerName.$invalid }">
    <div class="col-md-3">
      <div class="label-color">HEADER NAME 
        <span class="red"><strong>*</strong></span></div>
    </div>
    <div class="col-md-9">
      <input type="text" name="headerName" id="headerName" 
             ng-model="header.headerName" 
             maxlength="100" 
             class="form-control" required>
      <div ng-show="form.$submitted || form.headerName.$touched">
        <span ng-show="form.headerName.$invalid" 
              class="label-color validation-message">Header Name is required</span>
      </div>
    </div>
  </div>

  <button ng-click="addHeader(form, header)" 
          type="button" 
          class="btn btn-default pull-right">Add Header
  </button>

</form>

Trong bộ điều khiển của bạn, bạn có thể làm;

addHeader(form, header){
        let self = this;
        form.$submitted = true;
        ... 
    }

Bạn cũng cần một số css;

.label-color {
            color: $gray-color;
        }
.has-error {
       .label-color {
            color: rgb(221, 25, 29);
        }
        .select2-choice.ui-select-match.select2-default {
            border-color: #e84e40;
        }
    }
.validation-message {
       font-size: 0.875em;
    }
    .max-width {
        width: 100%;
        min-width: 100%;
    }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.