Виконайте перевірку всіх полів у поданні кутової форми


81

Я використовую цей метод: http://plnkr.co/edit/A6gvyoXbBd2kfToPmiiA?p=preview, щоб перевірити поля лише на розмиття. Це працює нормально, але я також хотів би перевірити їх (і, таким чином, показати помилки для цих полів, якщо такі є), коли користувач натискає кнопку "надіслати" (не справжнє надсилання, а виклик функції-ng-click функції)

Чи є спосіб запустити перевірку на всіх полях знову, натиснувши цю кнопку?


Де знаходиться кнопка в додатку?
callmekatootie

вибачте, на plunker я базував свій код .. Я зробив форк, щоб більш нагадувати свою ситуацію: plnkr.co/edit/VfvCSmjlzpIgUH4go2Jn?p=preview
Maarten

Відповіді:


44

Мені вдалося скористатися $setSubmittedфункцією, яка вперше з’являється у кутових документах у версії 1.3.20.

У випадку натискання, коли я хотів викликати перевірку, я зробив наступне:

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

Це було все, що потрібно для мене. Згідно з документами, він "встановлює форму до поданого стану". Це згадано тут .


4
це не працює, коли ви використовуєте, ng-messagesі показує їх лише тоді, коли $ error && $ брудні .
JobaDiniz

@JobaDiniz Ви пробували функцію $ setDirty? Це також згадується у посиланні з моєї відповіді: code.angularjs.org/1.3.20/docs/api/ng/type/form.FormController Сподіваюся, що це допоможе!
розробник

2
це не працює для form... Мені довелося прокрутити всі входи та викликати $setDirty()їх.
JobaDiniz

43

Я знаю, трохи пізно відповідати, але все, що вам потрібно зробити, це змусити всі форми забруднитися. Погляньте на наступний фрагмент:

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

а потім ви можете перевірити, чи правильно ваша форма, використовуючи:

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

і нарешті, я думаю, ви захочете змінити свій маршрут, якщо все виглядає добре:

$location.path('/somePath');

Редагувати : форма не реєструється в області, доки не спрацює подія подання. Просто використовуйте директиву ng-submit, щоб викликати функцію, і оберніть вищезазначене у цій функції, і вона повинна працювати.


1
Ви можете навести приклад ng-submitдирективи програмного запуску ?
човий

@chovy ng-submitпросто прив'язує функцію до події submit, чому б просто не викликати цю функцію?
Тілак Рао

у мене є директива, вбудована у форму, яка оновлює поле форми за межами директиви .... валідатор не застосовується, якщо я не клацну і розмию поле форми, яке хочу перевірити.
чови

у мене не буде об’єкта форми, який йому передається
chovy

@chovy Я вас неправильно розумію. Але дозвольте мені спробувати вам допомогти. Ви пробували перевірку при скасуванні?
Тілак Рао

17

На випадок, якщо хтось повернеться до цього пізніше ... Жодне з перерахованого не спрацювало для мене. Тож я заглибився в кишки перевірки кутової форми і знайшов функцію, яку вони викликають для виконання валідаторів на даному полі. Це помешкання зручно називати $validate.

Якщо у вас є названа форма myForm, ви можете програмно зателефонувати myForm.my_field.$validate()для виконання перевірки поля. Наприклад:

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

Зверніть увагу, що дзвінок $validateмає значення для вашої моделі. З кутових документів для ngModelCtrl. $ Validate:

Запускає кожен із зареєстрованих валідаторів (спочатку синхронних, а потім асинхронних валідаторів). Якщо дійсність зміниться на недійсну, для моделі буде встановлено значення undefined, якщо ngModelOptions.allowInvalid не відповідає істині. Якщо дійсність зміниться на дійсну, вона встановить для моделі останнє доступне дійсне значення $ modelValue, тобто або останнє проаналізоване значення, або останнє значення, встановлене з області дії.

Так що якщо ви плануєте робити що - то з неприпустимим значенням моделі (наприклад , вискакують повідомлення про їх так), то вам необхідно переконатися , що allowInvalidвстановлений в trueвашої моделі.


більше дискусії про дуже дивовижний результат "модель стає невизначеним" за відсутності allowInvalidможна прочитати тут: github.com/angular/angular.js/issues/10035
пестофаг

12

Ви можете використовувати Angular-Validator, щоб робити те, що хочете. Це просто безглуздо у використанні.

Це буде:

  • Перевіряйте лише поля на $dirtyабо наsubmit
  • Запобігання надсиланню форми, якщо вона недійсна
  • Показати власне повідомлення про помилку після того, як поле є $dirtyабо форма надіслана

Подивіться демо

Приклад

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

Якщо поле не пройде, validatorтоді користувач не зможе подати форму.

Перевіряти додатковими прикладами використання прикладів angular-validator та прикладами .

Застереження: Я є автором Angular-Validator


11

Ну, кутовий спосіб - це дозволити йому обробляти перевірку, - оскільки це відбувається при кожній зміні моделі - і відображати результат користувачеві лише тоді, коли ви хочете.

У цьому випадку ви вирішуєте, коли відображати помилки, вам просто потрібно встановити прапорець: http://plnkr.co/edit/0NNCpQKhbLTYMZaxMQ9l?p=preview

Наскільки я знаю, є проблема, подана до angular, щоб ми мали більш розширений контроль форми. Оскільки це не вирішено, я б використав це замість того, щоб винаходити всі існуючі методи перевірки.

редагувати: Але якщо ви наполягаєте на своєму шляху, ось ваша змінена скрипка з валідацією перед поданням. http://plnkr.co/edit/Xfr7X6JXPhY9lFL3hnOw?p=preview Контролер транслює подію, коли натискається кнопка, і директива робить магію перевірки.


Це працює в цьому прикладі, але що, якби я, як і в моєму випадку (але не в тому plunkr..вибачте!), Мав більше однієї директиви, як та електронна пошта. Чи потрібно мені якось переносити перевірку з директив в окремий клас перевірки, а потім викликати всі методи перевірки цієї форми, або я можу якось ініціювати перевірку іншим способом для всіх директив. Оскільки перевірка викликається розмиттям, можливо, навіть викликає розмиття з коду, але це здається жахливим.
Maarten

О, і я знаю про це питання. На жаль, це ще не в бета-версії, і робочий процес, про який я говорю, є обов’язковим для цієї компанії
Маартен,

Трансляційна подія спричинить зворотний виклик $ у кожній директиві, оскільки всі вони перебувають у межах контролера.
Олівер

ах..не дуже зрозумів цю частину. Дякую!
Maarten

1
Під час трансляції події ви можете передавати параметри. $ scope. $ broadcast ('startValidations', param1, param2); Прослуховування залишається незмінним: scope. $ On ('startValidations', validateMe); А у зворотному виклику fn: функція validateMe (подія, param1, param2) {} Див. Документацію: docs.angularjs.org/api/ng.$rootScope.Scope#$broadcast
Олівер

9

Один із підходів - примусити всі атрибути бути брудними. Це можна зробити на кожному контролері, але він стає дуже брудним. Краще було б мати загальне рішення.

Найпростіший спосіб, про який я міг придумати, - це скористатися директивою

  • він буде обробляти атрибут submit
  • він перебирає всі поля форми і позначає незаймані поля брудними
  • він перевіряє правильність форми перед викликом функції подання

Ось директива

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);
        }
      });
    }
  };
});

І оновіть форму html, наприклад:

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

стає:

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

Повний приклад дивіться тут: http://plunker.co/edit/QVbisEK2WEbORTAWL7Gu?p=preview


4

Ось моя глобальна функція для показу повідомлень про помилки форми.

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

І в моїх будь-яких контролерах,

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

1
Це не відповідає на питання.
Рафаель Герсковічі

Я змінив свою відповідь. Будь ласка, перевірте це зараз
Namal,

2

На основі відповіді Тілака я зміг придумати це рішення ...

Оскільки в моїх полях форми відображаються повідомлення про перевірку, лише якщо поле є недійсним, і користувач торкнувся його, я зміг використати цей код, викликаний кнопкою, щоб показати мої недійсні поля:

// 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

Примітка: Я знаю, що це хакерство, але це було корисно для Angular 1.2 і раніше, які не забезпечували простого механізму.

Перевірка запускає подію зміни , тому деякі речі, такі як програмне змінення значень, не спричинять її. Але активація події зміни спричинить перевірку. Наприклад, з jQuery:

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

Цей підхід простий. Плюс він має ту перевагу, що працює на старих (усіх) версіях Angular.
Paul LeBeau

3
Не той angular way.
Рафаель Герсковічі

0

Мені подобається такий підхід до обробки перевірки при натисканні кнопки.

  1. Не потрібно нічого викликати з контролера,

  2. все це обробляється директивою.

на github


0

Ви можете спробувати це:

// 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

Я зробив щось наступне, щоб це працювало.

<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>

У своєму контролері ви можете це зробити;

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

Вам також потрібно трохи 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%;
    }

0

Щоб перевірити всі поля моєї форми, коли я хочу, я перевіряю кожне поле елементів керування $$ наступним чином:

angular.forEach($scope.myform.$$controls, function (field) {
    field.$validate();
});
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.