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ฟังก์ชั่นจะถูกเรียกแม้ว่าอินพุตไม่ถูกต้อง เป็นไปได้หรือไม่ที่จะป้องกันพฤติกรรมนี้

ในฐานะที่เป็นบันทึกด้านข้างฉันสามารถพูดถึงว่าฉันใช้ bootstrap และ requirejs เช่นกัน



เราสามารถใช้งานได้โดยไม่มีแท็กแบบฟอร์มและยังคง form.valid จะทำงานใน NG-คลิก!
Rizwan Patel

คำตอบ:


329

คุณทำได้:

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

ไม่จำเป็นต้องตรวจสอบคอนโทรลเลอร์


8
นี่ควรเป็นคำตอบที่ยอมรับได้ ไม่จำเป็นต้องตรวจสอบอะไรในคอนโทรลเลอร์
Howie

10
ฉันไม่เห็นด้วยกับ "ไม่จำเป็นต้องตรวจสอบคอนโทรลเลอร์" จะเกิดอะไรขึ้นถ้าเราตรวจสอบการตรวจสอบความถูกต้องเพิ่มเติมเกิดขึ้นในฟังก์ชันส่ง
SlaterCodes

6
ทำการตรวจสอบเพิ่มเติมในคำสั่ง อัพเดตการตรวจสอบด้วย $ setValidity
TMB

@ b1tsh1ft มันจะดีกว่าที่จะให้สถานะปัจจุบันของการตรวจสอบเป็นที่รู้จักกันเสมอมากกว่าที่จะคิดออกเมื่อส่ง นั่นเป็นจุดรวมของการตรวจสอบเชิงมุม คุณไม่สามารถระบุสิ่งที่มองเห็นได้ของสถานะที่ไม่ถูกต้องเมื่อขอบเขตไม่ทราบ
Kevin Beal

1
ฉันได้ลองวิธีนี้แล้ว แต่ดูเหมือนว่ามันประเมินทั้งคู่ (เช่นมันไม่ทำให้บูลีนลัดวงจรหลังจากที่&&ฉันได้ลองผ่านค่าซึ่งเป็นส่วนหนึ่งของการส่งและยืนยันว่าค่าตัวเองเป็น "เท็จ"
Archimedes Trajano

67

เปลี่ยนปุ่มส่งเป็น:

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

1
คำตอบที่ดี คุณร็อค!
Harsha.Vaswani

24
คุณยังคงสามารถส่งแบบฟอร์มได้หากคุณกด Enter ในขณะที่ช่องป้อนข้อมูลมีโฟกัส!
fabsenet

2
@Red: ดูความคิดเห็นด้านบน
Andrei Rînea

ในขณะที่การปิดใช้งานปุ่มเป็นวิธีที่ดีที่สุดในการแก้ไขปัญหานี้ไม่ใช่สิ่งที่ OP ร้องขอ
มือขวา

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 เพื่อส่งฟังก์ชั่น: ฉันคิดว่า $ scope.loginform ควรมีอยู่ใน JS (อย่างน้อยก็สำหรับฉัน) ดังนั้นคุณสามารถแทนที่แบบฟอร์ม $ ใช้ได้กับ $ scope.loginform . $ ถูกต้อง
cellepo

13

แบบฟอร์มของคุณจะถูกใส่ใน $ scope โดยอัตโนมัติเป็นวัตถุ มันสามารถเข้าถึงได้ผ่านทาง$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
คุณจะเข้าถึงแบบฟอร์มได้อย่างไรถ้าคุณใช้สัญลักษณ์ "As Controller" แทน $ scope
masimplo

@masimakopoulos: คุณก็สามารถใช้if(this.loginform.$invalid).. แทน แต่แล้วใน HTML <form name="ctrl.loginform" ..ที่คุณได้ที่จะให้รูปแบบชื่อ และนั่นคือสมมติว่าคุณกำลังใช้<div ng-controller="controller as ctrl"..ในไวยากรณ์ตัวควบคุมของคุณ ขอบคุณ@JoshCaroll
Bart

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 ในความคิดของฉันมุมไม่ควรเรียก onsubmit เมื่อการป้อนข้อมูลไม่ถูกต้อง ดูbenlesh.com/2012/11/angular-js-form-validation.html การพูดว่า "ng-submit ไม่สามารถเรียกใช้ได้จนกว่าแบบฟอร์มทั้งหมดจะมีค่าเป็น $ valid"
Runar Halse

คุณสามารถปิดการใช้งานปุ่มเพื่อไม่ให้ส่งหากแบบฟอร์มนั้นถูกต้อง คุณสามารถใช้แบบฟอร์มและส่ง ng หากเชิงมุมไม่จัดการกับการตรวจสอบความถูกต้องของรูปแบบแล้วevent.preventDefault()เป็นวิธีที่จะไปหยุดการส่งแบบฟอร์ม
TheHippo

@RunarHalse มันจำเป็นจริงๆที่จะทำการตรวจสอบ ฉันเห็นด้วยกับคุณว่ามันไม่ควรเป็นอย่างนี้ เหตุผลที่ไม่ได้เรียกใช้เมธอด onsubmit ในตัวอย่างที่คุณเชื่อมโยงนั้นเป็นเพราะตัวอย่างนั้นไม่ได้มีการตั้งค่าใหม่เป็นโมฆะ เบราว์เซอร์กำลังป้องกันไม่ให้เหตุการณ์เพิ่มขึ้นไม่ใช่เชิงมุม นี่คือตัวอย่างของเขา W nobalidate / เมื่อ: plnkr.co/edit/R0C8XA?p=preview สังเกตเห็นการส่งแบบฟอร์ม
davidmdem

สมบูรณ์แบบในสิ่งที่ฉันกำลังมองหาวิธีบล็อกการส่งแบบฟอร์มโดยใช้เชิงมุม
setebos

3

แม้ว่าไม่ใช่วิธีแก้ปัญหาโดยตรงสำหรับคำถาม OPs หากแบบฟอร์มของคุณอยู่ใน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 เมื่อแบบฟอร์มนั้นถูกต้องปุ่ม "Clear Form" ก็จะถูกเรียกใช้ซึ่งเป็นการล้างทั้งฟอร์ม

เป็นวิธีแก้ปัญหา

ฉันต้องเพิ่มปุ่มส่งจำลองซึ่งถูกปิดใช้งานและซ่อนอยู่ และปุ่มนี้หุ่นจะต้องมีด้านบนของทุกปุ่มอื่น ๆ ที่แสดงด้านล่าง

<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 ในขณะที่ช่องป้อนข้อมูลมีโฟกัส!
Yevgeniy Afanasyev

0

ฉันรู้ว่ามันมาช้าและได้รับคำตอบ แต่ฉันต้องการแบ่งปันสิ่งที่ฉันทำไว้ให้เรียบร้อย ฉันสร้างคำสั่งตรวจสอบความถูกต้อง ng ที่ขอ onsubmit ของแบบฟอร์มจากนั้นมันจะออกค่าเริ่มต้นการป้องกันถ้า $ 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">
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.