如何验证 ngb-accordion 中的表单

How to Validate Forms inside an ngb-accordion

我实现了一个 ngb-accordion,其中包含一个带有几个输入字段的表单。我想在表单有效时显示一个带有复选标记的图标(在这种情况下,当所有表单都被填满而没有空字段时),而在所有其他情况下,它显示一个 'X' 标记图标。这些图标出现在标题前的 ngb-panel 标题中。

我将必需的 属性 分配给所有字段,并且组件文件中的方法检查表单是否有效。

SCSS 和 HTML 个文件-

input[type="text"],
select.form-control{
  background: transparent;
  border: none;
  border-bottom: 1px solid #000000;
  -webkit-box-shadow: none;
  box-shadow: none;
  border-radius: 0;
}
input[type="number"],
select.form-control{
  background: transparent;
  border: none;
  border-bottom: 1px solid #000000;
  -webkit-box-shadow: none;
  box-shadow: none;
  border-radius: 0;
}
input[type="text"]:focus,
select.form-control:focus {
  -webkit-box-shadow: none;
  box-shadow: none;
  border-color:rgb(31, 14, 187);
}
input[type="number"]:focus,
select.form-control:focus {
  -webkit-box-shadow: none;
  box-shadow: none;
  border-color:darkred;
}
::ng-deep .collapse {
    transition: max-height .55s, opacity .35s ease-in-out;
    max-height: 0;
    opacity: 0;
    display: block !important;
  
    &.show {
      max-height: 100rem;
      opacity: 1;
    }
  }
  
  ::ng-deep .accordion {
    .card {
      margin-bottom: 0 !important;
      border-bottom: 1px solid rgba(0, 0, 0, .04) !important;
  
      .card-header {
        // padding-top: 0;
        color: #000000;
        padding: 0;
  
        button {
          padding: 1.2rem;
          width: 100%;
  
          span {
            float: left;
            font-size: 1.2rem;
          }
        }
      }
  
      .card-body {
        padding: 1rem;
      }
    }
  }
 <div class="card">
        <div class="card-body">
           <!-- ngb Accordion starts -->
           <ngb-accordion [destroyOnHide]='false' [closeOthers]="true">
            
              <ngb-panel id="panel3">
                 <ng-template ngbPanelTitle>
                     <span *ngIf=" !myFormIsInvalid()">   <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-x-circle" viewBox="0 0 16 16">
                        <path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z"/>
                        <path d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z"
                        style="color: red;border-color: red;"/>
                        
                      </svg>&nbsp;</span>
                      <span><svg *ngIf="myFormIsInvalid()" xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-check-circle" viewBox="0 0 16 16">
                        <path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z"/>
                        <path d="M10.97 4.97a.235.235 0 0 0-.02.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-1.071-1.05z" style="color: green;"/>
                      </svg>&nbsp;</span>
                    <span>More Details </span>
                 </ng-template>
                 <ng-template ngbPanelContent>
     
                    <form #form3="ngForm" style="padding-left:20px;">
                
                        <div class="form-group">
                            <label for="name" class="control-label">Email<sup style="color: red;font-size:medium;">*</sup></label>
                            <input type="text" required #email ngModel name="Email" class="form-control" id="email">
                          </div>
                          <div class="form-group">
                            <label for="name" class="control-label">Phone<sup style="color: red;font-size:medium;">*</sup></label>
                            <input type="number" #phone ngModel required name="Phone" class="form-control" id="pone">
                          </div>  
                         
                          </form> 
                 </ng-template>
              </ngb-panel>
              
           </ngb-accordion>
          
        </div>
     </div>
    

Typescript 组件文件-

import { Component, OnInit } from '@angular/core';
import { ViewChild } from '@angular/core'
import { NgForm }   from '@angular/forms';

@Component({
  selector: 'app-collapsedemo',
  templateUrl: './collapsedemo.component.html',
  styleUrls: ['./collapsedemo.component.scss']
})
export class CollapsedemoComponent implements OnInit {

  @ViewChild('form3') myForm: NgForm | undefined;
  constructor() { }
  

  myFormIsInvalid(): boolean {
  
     
     if (this.myForm?.valid) {
         return true;
     }
     else
     {
     return false;}

  }


  
  
  ngOnInit(): void {
    
    
  }

}

下图是我得到的结果,但如果你仔细观察,我没有输入 Phone 字段,所以它应该还没有显示绿色勾号,它必须是 'X' 标记。出于某种原因,它只检查第一个字段是否已填充。如果第一个字段未填写,它会显示 'X' 图标,但当我只填写第一个字段时它会改变。

请告诉我为什么会这样,如果有其他方法可以满足我的要求,请同时提及最好的方法。

虽然您的检查函数被调用 myFormIsInvalid,但如果表单有效,它实际上会返回 true。所以首先改变你的功能:

myFormIsInvalid(): boolean {
     if (this.myForm?.valid) {
        return false;
     } else {
        return true;
     }
}

然后检查您是否在 HTML 模板中声明了正确的条件:因此 *ngIf="myFormIsInvalid()" 然后 color:red*ngIf="!myFormIsInvalid()" 然后 color:green

也就是说,您可以直接在模板中检查您的表单有效性,因为您有一个模板变量 #myForm*ngIf="myForm.valid"*ngIf="myForm.invalid"