访问 div 之外的 ngform 时出现错误 TS2339
error TS2339 while accessing an ngform outside a div
我有一个 angular 项目,我在其中使用了 ng-bootstrap 中的 ngb-accordion 来显示一些细节。我的手风琴反应灵敏。我在每个手风琴中都包含了表格。我有一个要求,我想在手风琴面板上方显示一个特定的图标,具体取决于里面的表格是有效还是无效。就像在手风琴内填写表格时,我想显示一个 bootstrap 勾号图标,如果它是错误的,那么我希望它显示一个十字标记图标。我尝试编写一个 ngIf
指令来检查表单对于包含图标的 div 是否有效。
下面是我尝试为一个手风琴实现上述功能的代码
HTML 文件
<head>
</head>
<body>
<div>
<div *ngIf="form1.invalid">
<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;
}
在行 <div *ngIf="form1.invalid">
它抛出一个错误说 src/app/collapsedemo/collapsedemo.component.html:9:21 - 错误 TS2339: 属性 'form1' 不存在 类型 'CollapsedemoComponent'。
请告诉我我做错了什么。当表单未填写时,我将在没有 ngIf
指令的情况下包含工作应用程序的图片。
另外,如果有的话,请建议我一个替代方案,我可以在 acoordion 面板本身的标题之前显示这些图标,比如让我们在上图中的“主要详细信息”标题之前而不是 ngb-panel。最终目标是在填写表单详细信息时显示绿色勾号,在手风琴内部未填写时显示十字标记。
表单在此位置不可用,因为它位于嵌套结构的较深处,而您在嵌套结构之外。
您可以使用 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()">
我有一个 angular 项目,我在其中使用了 ng-bootstrap 中的 ngb-accordion 来显示一些细节。我的手风琴反应灵敏。我在每个手风琴中都包含了表格。我有一个要求,我想在手风琴面板上方显示一个特定的图标,具体取决于里面的表格是有效还是无效。就像在手风琴内填写表格时,我想显示一个 bootstrap 勾号图标,如果它是错误的,那么我希望它显示一个十字标记图标。我尝试编写一个 ngIf
指令来检查表单对于包含图标的 div 是否有效。
下面是我尝试为一个手风琴实现上述功能的代码
HTML 文件
<head>
</head>
<body>
<div>
<div *ngIf="form1.invalid">
<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;
}
在行 <div *ngIf="form1.invalid">
它抛出一个错误说 src/app/collapsedemo/collapsedemo.component.html:9:21 - 错误 TS2339: 属性 'form1' 不存在 类型 'CollapsedemoComponent'。
请告诉我我做错了什么。当表单未填写时,我将在没有 ngIf
指令的情况下包含工作应用程序的图片。
另外,如果有的话,请建议我一个替代方案,我可以在 acoordion 面板本身的标题之前显示这些图标,比如让我们在上图中的“主要详细信息”标题之前而不是 ngb-panel。最终目标是在填写表单详细信息时显示绿色勾号,在手风琴内部未填写时显示十字标记。
表单在此位置不可用,因为它位于嵌套结构的较深处,而您在嵌套结构之外。
您可以使用 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()">