【问题标题】:error TS2339 while accessing an ngform outside a div访问 div 外的 ngform 时出现错误 TS2339
【发布时间】:2021-07-21 04:58:04
【问题描述】:

我有一个 Angular 项目,我使用来自 ng-bootstrap 的 ngb-accordion 来显示一些细节。我的手风琴反应灵敏。我在每个手风琴中都包含了表格。我有一个要求,我想在手风琴面板上方显示一个特定图标,具体取决于里面的表单是有效还是无效。就像在手风琴内填写表格时,我想显示一个引导刻度图标,如果它是错误的,那么我希望它显示一个十字标记图标。我尝试编写一个ngIf 指令来检查表单对于包含图标的 div 是否有效。

下面是我尝试为一架手风琴实现上述功能的代码

HTML 文件

 <head>
</head>

<body>
<div>
    <div *ngIf="form1.invalid">
        &nbsp;
        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" 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;"/>
          </svg>
    </div>
    
    <div>
<ngb-accordion #acc="ngbAccordion">
    <ngb-panel id="toggle-1" title="Primary Details" >
      <ng-template ngbPanelContent>
        <form #form1="ngForm" style="padding-left:20px;">
            
            <div class="form-group">
                <label for="name" class="control-label">First Name<sup style="color: red;font-size:medium;">*</sup></label>
                <input type="text" ngModel name="FirstName" class="form-control" id="FirstName">
              </div>
           
              <div class="form-group">
                <label for="name" class="control-label">Last Name<sup style="color: red;font-size:medium;">*</sup></label>
                <input type="text" name="LastName" class="form-control" id="LastName">
              </div>
              <div class="form-group">
                <label for="name" class="control-label">Organization<sup style="color: red;font-size:medium;">*</sup></label>
                <input type="text" name="name" class="form-control" id="name">
              </div>
              </form> 
      </ng-template>
    </ngb-panel>
  </ngb-accordion>
  </div>
  </div>
  <br>
  <ngb-accordion #acc="ngbAccordion">
    <ngb-panel id="toggle-2" title="Secondary Details">
      <ng-template ngbPanelContent>
        <form #form2="ngForm" style="padding-left:20px;">
            
            <div class="form-group">
                <label for="name" class="control-label">Address<sup style="color: red;font-size:medium;">*</sup></label>
                <input type="text" name="Address" class="form-control" id="name">
              </div>
              <div class="form-group">
                <label for="dropdown-test" class="control-label">City<sup style="color: red;font-size:medium;">*</sup></label>
              
                <select class="form-control" name="dropdown-test">
                <option>select an option</option>
                <option>option2</option>
                <option>option3</option>
                <option>option4</option>
                <option>option5</option>
              </select>
              </div>  
             
              </form> 
      </ng-template>
    </ngb-panel>
    
  </ngb-accordion>
  <br>
  <ngb-accordion #acc="ngbAccordion">
    <ngb-panel id="toggle-3" title="More Details">
      <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" name="Email" class="form-control" id="name">
              </div>
              <div class="form-group">
                <label for="name" class="control-label">Phone<sup style="color: red;font-size:medium;">*</sup></label>
                <input type="number" name="Phone" class="form-control" id="name">
              </div>  
             
              </form> 
      </ng-template>
    </ngb-panel>
    
  </ngb-accordion>
  
  
 </body>

CSS 文件

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

&lt;div *ngIf="form1.invalid"&gt; 行,它向我抛出一个错误,提示 src/app/collapsedemo/collapsedemo.component.html:9:21 - error TS2339: Property 'form1' does not exist 在类型“CollapsedemoComponent”上。

请告诉我我做错了什么。当表格未填写时,我将包含没有ngIf 指令的工作应用程序的图片。

如果有的话,请给我建议一个替代方案,我可以在标题之前的 acoordion 面板中显示这些图标,就像让我们在上图中的“主要详细信息”标题之前而不是在 ngb 面板上方说的那样.最终的目标是当表单详细信息被填写时显示一个绿色的勾号,当它在手风琴内部没有填写时显示一个叉号。

【问题讨论】:

    标签: angular typescript twitter-bootstrap accordion ng-bootstrap


    【解决方案1】:

    该表格在此位置不可用,因为它位于嵌套结构的更深处,而您在它之外。

    您可以使用 ViewChild 指令和方法来实现您想要的。我会告诉你怎么做。

    第一步

    在 TS 文件中获取表单的 ViewChild。

    @ViewChild('form1') myForm: NgForm | undefined;
    

    第二步

    编写一个方法,您可以使用该方法获取视图子的状态。

    注意!如果您不等待,您将遇到ExpressionChangedAfterItHasBeenCheckedError。这是因为您的表单状态在开始时是undefined,而当它获得true 时,您的HTML 的其余部分最终不会由Angular 呈现。所以我想出了一种方法来处理这种竞争条件。

    // shows whether the view is rendered entirely
    private viewRendered = false;
    
    // returns the current state of your form1
    myFormIsInvalid(): boolean {
    
       // only return the actual state, when the view is rendered entirely
       if (this.viewRendered) {
           return !(this.myForm && this.myForm.valid);
       }
    
       return false;
    }
    

    然后我们需要在ngOnInit() 中设置一点超时,以便在应该加载整个表单时释放您的方法。

    ngOnInit(): void {
        // after 250ms set the method myFormIsValid() free to return the actual value
        setTimeout(() => {
            this.viewRendered = true;
        }, 250);
    }
    

    第三步

    In your HTML: Use the method here to get the state of the form
    
    <div *ngIf="myFormIsInvalid()">
    

    【讨论】:

    • 谢谢!但是当手风琴关闭时,图标会消失。每当表格未填写时,我希望它一直存在。即使我填写了所有字段,图标也不会消失。
    • 对不起,我的错。我没有发现您想在表单无效时查看图标。我编辑了方法名称和它返回的结果。请再试一次。
    • 我试过修改它,你可以检查一下吗?pastebin.com/0eSihkDp 但它仍然无法正常工作
    • 您必须将您的代码否定为if (!this.myForm?.valid){}。正如我所说,我认为您想在表单有效时查看图标。但它的方法名现在最好是myFormIsInvalid()。只是为了使其简洁。请再试一次。
    • 对不起,如果我没有把我的要求说得很清楚。我会再说一遍。我有两个 div 一个包含“X”图标,当表单无效时必须始终呈现。另一个 div 包含必须在表单有效时呈现的刻度线图标。我打算使用 ngif else 指令来实现这一点,正如我在我之前发布的链接中的评论中提到的那样。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-12
    • 1970-01-01
    • 1970-01-01
    • 2020-03-15
    • 2020-06-03
    • 2017-11-04
    相关资源
    最近更新 更多