วิธีค้นหาตัวควบคุมที่ไม่ถูกต้องในรูปแบบปฏิกิริยาเชิงมุม 4


92

ฉันมีรูปแบบปฏิกิริยาในเชิงมุมดังต่อไปนี้:

this.AddCustomerForm = this.formBuilder.group({
    Firstname: ['', Validators.required],
    Lastname: ['', Validators.required],
    Email: ['', Validators.required, Validators.pattern(this.EMAIL_REGEX)],
    Picture: [''],
    Username: ['', Validators.required],
    Password: ['', Validators.required],
    Address: ['', Validators.required],
    Postcode: ['', Validators.required],
    City: ['', Validators.required],
    Country: ['', Validators.required]
});

createCustomer(currentCustomer: Customer) 
{
    if (!this.AddCustomerForm.valid)
    {
        //some app logic
    }
}

this.AddCustomerForm.valid ส่งคืนเท็จ แต่ทุกอย่างดูดี

ฉันได้พยายามค้นหาด้วยการตรวจสอบคุณสมบัติสถานะในคอลเล็กชันการควบคุม แต่ฉันสงสัยว่ามีวิธีค้นหาสิ่งที่ไม่ถูกต้องและแสดงต่อผู้ใช้หรือไม่?


คุณเพียงแค่ต้องการแสดงฟิลด์ที่มีข้อผิดพลาดคุณสามารถใช้ css เพื่อไฮไลต์หรือระบายสีฟิลด์ที่ไม่ถูกต้อง แต่ละช่องที่ไม่ถูกต้องจะมีคลาส "ng-invalid" ต่อท้ายในรายการคลาส
LookForAngular

คำตอบ:


176

คุณสามารถทำซ้ำทุกการควบคุมและตรวจสอบสถานะ:

    public findInvalidControls() {
        const invalid = [];
        const controls = this.AddCustomerForm.controls;
        for (const name in controls) {
            if (controls[name].invalid) {
                invalid.push(name);
            }
        }
        return invalid;
    }

1
ขอบคุณสำหรับสิ่งนี้ แต่ฉันได้ลองสิ่งนี้แล้วและถึงแม้สิ่งนี้จะไม่ส่งคืนฟอร์มของฉันก็ยังไม่ถูกต้องนี่เป็นเรื่องแปลก ฉันหมายความว่ารหัสนี้ดูดี แต่ก็ไม่สมเหตุสมผลว่าทำไม form.valid คืนค่าเท็จ
sa_

อะไรfindInvalidControls()ตอบแทนคุณ?
Max Koretskyi

1
มันไม่ส่งคืนอะไรเลยไม่ถูกต้องว่างเปล่า ฉันตรวจสอบทีละรายการในหน้าจอนาฬิกาดีบักการควบคุมทั้งหมดใช้ได้ แต่สิ่งนี้ AddCustomerForm.valid ยังคงส่งคืนเท็จ
sa_

ฉันคิดว่าฉันค้นพบแล้ว มีฟิลด์อีเมลและนิพจน์ทั่วไป แต่สถานะของตัวควบคุมคือ PENDING และอาจเป็นสาเหตุ
sa_

7
@ AngularInDepth.com - ถ้าตัวควบคุมตัวใดตัวหนึ่งเป็นกลุ่มฟอร์มฟังก์ชันของคุณจะส่งคืนกลุ่มฟอร์มที่ไม่ถูกต้องและไม่ใช่ตัวควบคุมฟอร์มเฉพาะที่ไม่ถูกต้อง
john Smith

36

ฉันเพิ่งต่อสู้กับปัญหานี้: ช่องฟอร์มทุกช่องถูกต้อง แต่ฟอร์มยังไม่ถูกต้อง

ปรากฎว่าฉันได้ตั้งค่า 'Validator.required' บน FormArray ที่มีการเพิ่ม / ลบการควบคุมแบบไดนามิก ดังนั้นแม้ว่า FormArray จะว่างเปล่า แต่ก็ยังจำเป็นต้องใช้ดังนั้นฟอร์มจึงไม่ถูกต้องเสมอแม้ว่าทุกตัวควบคุมที่มองเห็นจะถูกเติมอย่างถูกต้องก็ตาม

ฉันไม่พบส่วนที่ไม่ถูกต้องของแบบฟอร์มเนื่องจากฟังก์ชัน 'findInvalidControls' ของฉันตรวจสอบเฉพาะ FormControl ไม่ใช่ FormGroup / FormArray ดังนั้นฉันจึงอัปเดตเล็กน้อย:

/* 
   Returns an array of invalid control/group names, or a zero-length array if 
   no invalid controls/groups where found 
*/
public findInvalidControlsRecursive(formToInvestigate:FormGroup|FormArray):string[] {
    var invalidControls:string[] = [];
    let recursiveFunc = (form:FormGroup|FormArray) => {
      Object.keys(form.controls).forEach(field => { 
        const control = form.get(field);
        if (control.invalid) invalidControls.push(field);
        if (control instanceof FormGroup) {
          recursiveFunc(control);
        } else if (control instanceof FormArray) {
          recursiveFunc(control);
        }        
      });
    }
    recursiveFunc(formToInvestigate);
    return invalidControls;
  }

3
คำตอบที่มีประโยชน์อย่างไม่น่าเชื่อ ขอบคุณมาก
Mikki

1
เห็นด้วยคำตอบที่มีประโยชน์มาก
nenea

24

ตัวควบคุมเชิงมุมที่ไม่ถูกต้องมีคลาส CSS ที่มีชื่อว่า'NG-ที่ไม่ถูกต้อง'

ภายใต้ DevTools ใน Chrome เลือกแท็บคอนโซล

ในคำสั่งประเภทพรอมต์คอนโซล:

document.getElementsByClassName('ng-invalid')

ผลลัพธ์ควรคล้ายกับสิ่งนี้: ป้อนคำอธิบายภาพที่นี่

listen-addressในกรณีนี้ข้อความที่ขีดเส้นใต้คือสำหรับการควบคุมรูปแบบ และข้อความที่ล้อมรอบ: .ng-invalidบ่งชี้ว่าการควบคุมไม่ถูกต้อง

หมายเหตุ: ทดสอบในโครเมี่ยม


2
สิ่งนี้สำหรับฉันดูเหมือนจะเป็นวิธีที่ตรงที่สุดในการตอบคำถาม
ckapilla

2
คุณช่วยฉันจากการเป็นบ้าถ้าฉันสามารถซื้อเครื่องดื่มให้คุณได้
Adam Winnipass

3

ทั้งแบบฟอร์มและการควบคุมทั้งหมดของคุณขยายคลาสเชิงมุม AbstractControl การนำไปใช้งานแต่ละครั้งมีตัวเข้าถึงข้อผิดพลาดในการตรวจสอบความถูกต้อง

let errors = this.AddCustomerForm.errors
// errors is an instance of ValidatorErrors

เอกสาร api มีข้อมูลอ้างอิงทั้งหมด https://angular.io/api/forms/AbstractControl

แก้ไข

ฉันคิดว่าตัวเข้าถึงข้อผิดพลาดทำงานในลักษณะนี้อย่างไรก็ตามลิงก์นี้ไปยัง github แสดงให้เห็นว่ามีคนอื่น ๆ ที่คิดเหมือนกันกับฉัน https://github.com/angular/angular/issues/11530

ไม่ว่าในกรณีใดก็ตามโดยใช้ตัวควบคุมการเข้าถึงคุณสามารถวนซ้ำบน formControls ทั้งหมดในแบบฟอร์มของคุณ

Object.keys(this.AddCustomerForm.controls)
    .forEach( control => {
        //check each control here
        // if the child is a formGroup or a formArray
        // you may cast it and check it's subcontrols too
     })

1
ผลตอบแทนนี้ null แม้มีการควบคุมที่ว่างเปล่า
sÃ_

1
ควรคืนค่าว่างเมื่อไม่มีข้อผิดพลาด คุณสามารถโพสต์เทมเพลตของคุณได้หรือไม่?
LookForAngular

ใช่วิธีนี้ใช้ไม่ได้การตรวจสอบความถูกต้องที่แตกต่างกันที่ตั้งค่าไว้ในตัวควบคุมฟอร์มแต่ละตัวการควบคุมแต่ละแบบมีข้อผิดพลาดแบบฟอร์มไม่ได้ คุณต้องวนซ้ำการควบคุมเช่น Maximus ให้คำตอบ
AJT82

ฉันสามารถเข้าถึงข้อผิดพลาดสำหรับแต่ละ contorls เช่น this.form.controls ['อีเมล'] ข้อผิดพลาด
Nazrul Muhaimin

@ AJT_82 แน่นอนว่าแบบฟอร์มสามารถแสดงข้อผิดพลาดได้หากมีการตั้งค่าตัวตรวจสอบความถูกต้องสำหรับ formGroup (ตรวจสอบเอกสารเกี่ยวกับการตรวจสอบความถูกต้องข้ามเขตข้อมูลซึ่งเหมาะสมในการตรวจสอบความถูกต้องในกลุ่มและไม่อยู่ในการควบคุม)
LookForAngular

3

ตอนนี้ในเชิงมุม 9 คุณสามารถใช้เมธอด markAllAsTouched () เพื่อแสดงตัวตรวจสอบการควบคุมที่ไม่ถูกต้อง:

this.AddCustomerForm.markAllAsTouched();

จะให้ +1 นี้เพราะมันช่วยให้ฉันค้นพบสิ่งที่ฉันจำเป็นต้องรู้ --- ซึ่งก็คือการแสดงข้อความตรวจสอบความถูกต้องเมื่อผู้ใช้ไม่จำเป็นต้องสัมผัสอินพุต
Sean Halls

1

หากคุณไม่มีฟิลด์มากนักในแบบฟอร์มคุณสามารถเพียงแค่ F12 และวางเมาส์เหนือการควบคุมคุณจะสามารถเห็นป๊อปอัปที่มีค่าที่เก่าแก่ / สัมผัส / ถูกต้องของฟิลด์ - "# fieldname.form-control.ng- untouched.ng-invalid ".


1

ฉันคิดว่าคุณควรลองใช้this.form.updateValueAndValidity()หรือลองใช้วิธีเดียวกันนี้ในแต่ละส่วนควบคุม



1

สิ่งนี้จะบันทึกชื่อตัวควบคุมทั้งหมด😊

for (let el in this.ReactiveForm.controls) {
      if (this.ReactiveForm.controls[el].errors) {
        console.log(el)
      }
 }          

คุณสามารถสร้างอาร์เรย์หรือสตริงจากสิ่งนี้และแสดงต่อผู้ใช้


0

ฉันใช้เสรีภาพในการปรับปรุงโค้ด AngularInDepth.com -s เพื่อให้ค้นหาอินพุตที่ไม่ถูกต้องซ้ำ ๆ ในรูปแบบที่ซ้อนกันด้วย เชื่อมต่อกันโดย FormArray-s หรือ FormGroup-s เพียงป้อน formGroup ระดับบนสุดและจะส่งคืน FormControls ทั้งหมดที่ไม่ถูกต้อง

คุณสามารถข้ามการตรวจสอบประเภท "instanceof" บางส่วนไปได้หากคุณจะแยกการตรวจสอบ FormControl และเพิ่มฟังก์ชันอาร์เรย์ที่ไม่ถูกต้องออกเป็นฟังก์ชันแยกต่างหาก สิ่งนี้จะทำให้ฟังก์ชั่นดูสะอาดขึ้นมาก แต่ฉันต้องการตัวเลือกทั่วโลกฟังก์ชั่นเดียวเพื่อรับอาร์เรย์แบบแบนของ formControls ที่ไม่ถูกต้องทั้งหมดและนี่คือวิธีแก้ปัญหา!

findInvalidControls( _input: AbstractControl, _invalidControls: AbstractControl[] ): AbstractControl[] {
    if ( ! _invalidControls ) _invalidControls = [];
    if ( _input instanceof FormControl  ) {
        if ( _input.invalid ) _invalidControls.push( _input );
        return _invalidControls;
    }

    if ( ! (_input instanceof FormArray) && ! (_input instanceof FormGroup) ) return _invalidControls;

    const controls = _input.controls;
    for (const name in controls) {
        let control = controls[name];
        switch( control.constructor.name )
        {
            case 'AbstractControl':
            case 'FormControl':
                if (control.invalid) _invalidControls.push( control );
                break;

            case 'FormArray':
                (<FormArray> control ).controls.forEach( _control => _invalidControls = findInvalidControls( _control, _invalidControls ) );
                break;

            case 'FormGroup':
                _invalidControls = findInvalidControls( control, _invalidControls );
                break;
        }
    }

    return _invalidControls;
}

สำหรับผู้ที่ต้องการเท่านั้นจึงไม่ต้องเขียนโค้ดเอง ..

แก้ไข # 1

ขอให้ส่งคืน FormArray-s และ FormGroups ที่ไม่ถูกต้องด้วยดังนั้นหากคุณต้องการสิ่งนั้นให้ใช้รหัสนี้

findInvalidControls( _input: AbstractControl, _invalidControls: AbstractControl[] ): AbstractControl[] {
    if ( ! _invalidControls ) _invalidControls = [];
    if ( _input instanceof FormControl  ) {
        if ( _input.invalid ) _invalidControls.push( _input );
        return _invalidControls;
    }

    if ( ! (_input instanceof FormArray) && ! (_input instanceof FormGroup) ) return _invalidControls;

    const controls = _input.controls;
    for (const name in controls) {
        let control = controls[name];
        if (control.invalid) _invalidControls.push( control );
        switch( control.constructor.name )
        {    
            case 'FormArray':
                (<FormArray> control ).controls.forEach( _control => _invalidControls = findInvalidControls( _control, _invalidControls ) );
                break;

            case 'FormGroup':
                _invalidControls = findInvalidControls( control, _invalidControls );
                break;
        }
    }

    return _invalidControls;
}

1
ฉันลองแล้ว แต่ไม่พบ FormGroup หรือ FormArray ที่ไม่ถูกต้อง ... มีเพียง FormControl ที่ไม่ถูกต้องเท่านั้น ฉันทำผิดเหมือนกัน ... ดูคำตอบของฉัน
Jette

ฉันปรับปรุงคำตอบของฉันเพื่อให้เหมาะกับกรณีการใช้งานของคุณ
Karl Johan Vallner

0

คุณสามารถบันทึกค่าของฟอร์มconsole.log(this.addCustomerForm.value)มันจะคอนโซลค่าของตัวควบคุมทั้งหมดจากนั้นเป็นค่าว่างหรือฟิลด์ "" (ว่าง) บ่งบอกถึงการควบคุมที่ไม่ถูกต้อง


0

หากคุณต้องการตรวจสอบว่าแบบฟอร์มถูกต้องหรือไม่และไม่ต้องการเปลี่ยนแปลงโค้ดใด ๆ คุณสามารถลองเรียกใช้คำสั่งต่อไปนี้ใน Chrome Developer Tool Console โปรดตรวจสอบให้แน่ใจว่าแอปเชิงมุมของคุณกำลังแสดงส่วนประกอบที่โฮสต์แบบฟอร์มดังกล่าว

ng.probe(document.querySelector("app-your-component-selector-name")).componentInstance;

อย่าลืมแทนที่ชื่อตัวเลือกส่วนประกอบของคุณในคำสั่งด้านบน

AddCustomerFormคำสั่งนี้จะแสดงรายการตัวแปรทั้งหมดจากองค์ประกอบของคุณรวมถึง ตอนนี้ถ้าคุณขยายสิ่งนี้คุณจะเห็นรายการการควบคุมทั้งหมดของคุณ จากนั้นคุณสามารถขยายแต่ละตัวควบคุมเพื่อตรวจสอบว่าถูกต้องหรือไม่


-1

ตรวจสอบค่าการควบคุมฟอร์มว่างหรือค่าว่างในหน้า html

ค่าตัวควบคุมฟอร์ม: {{formname.value | json}}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.