Angularjs запобігає надсиланню форми, коли перевірка введення не вдається


155

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

<form name="loginform" novalidate ng-submit="login.submit()" class="css-form">
    <fieldset>

        <div class="control-group input-prepend">
            <span class="add-on"><i class="icon-user"></i></span>
            <input type="text" ng-model="login.username" name="username" required ng-minlength="3" placeholder="username" />
        </div>

        <div class="control-group input-prepend">
            <span class="add-on"><i class="icon-lock"></i></span>
            <input type="password" ng-model="login.password" name="password" required ng-minlength="3" placeholder="" />
        </div>

        <div class="control-group">
            <input class="btn" type="submit" value="Log in">
        </div>

    </fieldset>
</form>

І контролер:

var controller = function($scope) {

    $scope.login = {
        submit: function() {

            Console.info($scope.login.username + ' ' + $scope.login.password);
        }
    }

};

Проблема полягає в тому, що login.submitфункція буде викликана, навіть якщо введення недійсне. Чи можна запобігти такій поведінці?

В якості бічної записки можу зазначити, що я також використовую завантажувальний і запуск.



чи можемо ми використовувати його без тегу форми та ще form.valid буде працювати на ng-клацання!
Rizwan Patel

Відповіді:


329

Ви можете зробити:

<form name="loginform" novalidate ng-submit="loginform.$valid && login.submit()">

Не потрібно перевірки контролера.


8
Це має бути прийнятою відповіддю. Не потрібно нічого перевіряти в контролері
Howie

10
Я не згоден з "відсутністю необхідності перевірки контролера". Що робити, якщо у функції подання відбудуться додаткові перевірки перевірки.
SlaterCodes

6
Виконайте додаткову перевірку в директиві. Оновіть перевірку за допомогою $ setValidity.
TMB

@ b1tsh1ft Переважно, щоб поточний стан перевірки завжди був відомим, а не з'ясованим після подання. Це якось уся суть валідації кута. Ви не можете мати жодної візуальної індикації недійсного стану, коли область не знає про це.
Кевін Біл

1
Я спробував такий підхід, але, схоже, він оцінює обидва (тобто він не має короткого замикання булевого типу після того, як &&я спробував передати значення як частину подання і підтвердив, що саме значення "помилкове"
Архімед Траяно

67

Змініть кнопку для надсилання на:

<button type="submit" ng-disabled="loginform.$invalid">Login</button>

1
Чудова відповідь. Ти рок!
Харша.Васвані

24
Ви все ще можете надіслати форму, якщо натиснути клавішу Enter, поки фокус поля введення!
fabsenet

2
@Red: Дивіться коментар вище.
Андрій Ронеа

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

1
Поєднання цієї методики для надання візуального зворотного зв’язку для користувача разом із відповіддю @Yashua для запобігання надсилання форми є ідеальним. Дякую!
tkarls

43

Тож запропонована відповідь від TheHippo для мене не спрацювала, натомість я в кінцевому підсумку надіслав форму як параметр функції як:

<form name="loginform" novalidate ng-submit="login.submit(loginForm)" class="css-form">

Це робить форму доступною в методі контролера:

$scope.login = {
    submit : function(form) {
        if(form.$valid)....
    }

У мене було те саме питання. Однак, використовуючи свій метод, працювало.
Panda4Man

Це трохи краще, ніж прийнятий відповідь, тому що форма. $ Дійсна перевірка робиться в JS, а не в HTML.
cellepo

Однак я не думаю, що вам потрібно пройти loginForm, щоб надіслати функцію: я думаю, що $ range.loginform повинен бути доступний у JS (принаймні, це було для мене), щоб ви могли замінити форму. . $ дійсно.
cellepo

13

Ваші форми автоматично вводяться в область "$" як об'єкт. Доступ до нього можна отримати через$scope[formName]

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

var controller = function($scope) {

    $scope.login = {
        submit: function() {
            if($scope.loginform.$invalid) return false;

        }
    }

};

Приклад роботи: http://plnkr.co/edit/BEWnrP?p=preview


4
Як би ви отримали доступ до форми, якщо ви використовуєте позначення "Як контролер" замість $ ""?
masimplo

@masimakopoulos: Ви можете просто використовувати if(this.loginform.$invalid).. замість цього, але тоді в HTML ви повинні дати назву форми <form name="ctrl.loginform" ... І це припускаючи, що ви використовуєте <div ng-controller="controller as ctrl"..в контролері як синтаксис. Дякуємо @JoshCaroll
Барт

13

HTML:

<div class="control-group">
    <input class="btn" type="submit" value="Log in" ng-click="login.onSubmit($event)">
</div>

У вашому контролері:

$scope.login = {
    onSubmit: function(event) {
        if (dataIsntValid) {
            displayErrors();
            event.preventDefault();
        }
        else {
            submitData();
        }
    }
}

чи дійсно потрібно робити перевірку в рамках методу onsubmit? Це означає, що ви повинні перевірити, що вхід відповідає всім критеріям як у розмітці (через кутовий), так і в коді js. На мою думку, кутовий не повинен викликати підписку, коли вхід недійсний. дивіться benlesh.com/2012/11/angular-js-form-validation.html, кажучи, що "ng-submit не можна викликати, поки вся форма не буде дійсною"
Runar Halse

Ви також можете відключити кнопку, щоб заборонити надсилання, якщо форма дійсна. Ви також можете скористатися формою ng-submit. Якщо кутовий не обробляє перевірку форми, тоді event.preventDefault()це шлях, щоб зупинити подання форми.
TheHippo

@RunarHalse Це дійсно потрібно зробити перевірку. Я згоден з вами, що так не повинно бути. Причина того, що метод onsubmit не викликається у прикладі, який ви пов’язали, полягає в тому, що в цьому прикладі не встановлено недійсний набір. Веб-переглядач заважає підвищувати події, а не кутовий. Ось його приклад w / nobalidate на: plnkr.co/edit/R0C8XA?p=preview . Повідомте, що форма подається.
davidmdem

ідеально просто те, що я шукав, спосіб заблокувати подання форми за допомогою кутового
setebos

3

Хоча це не пряме рішення для питання про ОП, якщо ваша форма знаходиться в ng-appконтексті, але ви хочете, щоб Angular цілком її ігнорував, ви можете це зробити прямо, використовуючи ngNonBindableдирективу:

<form ng-non-bindable>
  ...
</form>

2

Просто щоб додати відповіді вище,

У мене були 2 звичайні кнопки, як показано нижче. (Ніде немає типу = "подати" ніде)

<button ng-click="clearAll();" class="btn btn-default">Clear Form</button>
<button ng-disabled="form.$invalid" ng-click="submit();"class="btn btn-primary pull-right">Submit</button>

Скільки б я не намагався, натискаючи клавішу Enter, коли форма була дійсною , була викликана кнопка "Очистити форму", очищаючи всю форму.

Як вирішення,

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

<button type="submit" ng-hide="true" ng-disabled="true">Dummy</button>

<button ng-click="clearAll();" class="btn btn-default">Clear Form</button>

<button ng-disabled="form.$invalid" ng-click="submit();"class="btn btn-primary pull-right">Submit</button>

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


ви можете зупинити подання на натисніть Enter, також видаливши атрибут on ng-submit зі своєї форми
Kieran

1

Я знаю, що це стара тема, але я подумав, що також я вкладу. Моє рішення подібне до публікації, яка вже позначена як відповідь. Деякі вбудовані перевірки JavaScript робить свою справу.

ng-click="form.$invalid ? alert('Please correct the form') : saveTask(task)"

1
Ви все ще можете надіслати форму, якщо натиснути клавішу Enter, поки фокус поля введення!
Євген Афанасьєв

0

Я знаю, що пізно і мені відповіли, але я хотів би поділитися акуратними речами, які я зробив. Я створив ng-validate директиву, яка зачіплює підписку форми, тоді вона видає запобігання-за замовчуванням, якщо $ eval невірно:

app.directive('ngValidate', function() {
  return function(scope, element, attrs) {
    if (!element.is('form'))
        throw new Error("ng-validate must be set on a form elment!");

    element.bind("submit", function(event) {
        if (!scope.$eval(attrs.ngValidate, {'$event': event}))
            event.preventDefault();
        if (!scope.$$phase)
            scope.$digest();            
    });
  };
});

У вашому html:

<form name="offering" method="post" action="offer" ng-validate="<boolean expression">
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.