如何根据 angular FormGroup 中的输入字段数据可用性来启用或禁用按钮?
How to button enable or disable according to input field data availability in angular FormGroup?
我的表单输入字段是否需要根据API数据集决定。但是当它是强制性的时,我需要禁用按钮,直到用户输入一些值。我是 angular 中反应式形式的绝对初学者。需要一些专家的帮助才能做到这一点。
------------HTML---------------------
<div class="a">
<at-card *ngIf="selectedId$|async" class="b">
<at-detail [selectedDetail]="selectedDetailModel$|async">
</at-detail>
<div [formGroup]="DetailForm" class="grid grid-columns-2">
<br />
<mat-form-field>
<mat-label>Comment</mat-label>
<input matInput formControlName="comment" [type]="'text'" [required]="commentRequerd">
</mat-form-field>
</div>
</at-card>
<at-sticky-footer>
<button *ngIf="selectedId$|async" (click)="onSubmit()">submit</button>
</at-sticky-footer>
</div>
-----------------component.ts-----------------
commentRequerd: boolean;
DetailForm = new FormGroup({ comment: new FormControl(), rate: new FormControl() });
ngOnInit(): void {
inputCommentIsMandotory:boolean = <take API data about enter comment needed or not>
//accroding to that input comment filed mark as requred->
//is it requred need to check user input data to comment field ->
//if it avalable button is enable , else it disable
if(inputCommentIsMandotory){
this.commentRequerd = true;
//when user enter data button enable , if not disable(input field empty)
}else{
//alwasy button enable (input comment or not)
this.commentRequerd = false;
}
}
----------------最新更新(按钮始终禁用,即使评论不是强制性的------------ ----------------------
我像下面这样更改了代码。
isCommentMandatory(Reviews: ReviewModel[]): void {
if (Reviews.length > 0) {
console.log("called ...1 ");
this.isCommentRequired = false;
this.DetailForm = this.fb.group({
comment: [''],
rate: ['']
});
} else {
console.log("called ...2 ");
this.isCommentRequired = true;
this.DetailForm = this.fb.group({
comment: ['', Validators.required],
rate: ['']
});
}
}
并这样称呼它,
ngOnInit(): void {
this.DetailModel$.pipe().subscribe((opd => {
this.detail = opd as Detail;
const date = this.detail?.time;
const planDate = date !== undefined ? date : new Date();
//according date select reviews data
this.store.select(selectAllReviewsDetailsModel(planDate)).
subscribe(res => this.Reviews = res);
//need to call after change Details
this.isCommentMandatory(this.Reviews);
}));
}
在下面的 html 模板中,
<at-sticky-footer>
<button *ngIf="selectedId$|async" [disabled]="!(DetailModel.valid && (DetailModel.dirty))" (click)="submit()">submit</button>
</at-sticky-footer>
但是现在,这两种情况都需要输入一些内容来启用按钮。
反应式表单的想法是单向数据流。数据从组件流向模板;当用户处理完数据后,他们单击“保存”,组件再次接管。
如果需要数据验证,则在 组件中完成,如果存在更改数据的条件逻辑,则在组件中完成。如果有行为(但没有数据或验证更改),那么它是一个模板指令就可以了。 (作为 'for instance',弹出“此行已更改”视觉指示器作为突出显示在模板中作为指令非常好)。
您表单中的所有控件都是 Observable;这意味着您可以观察它们在组件和 'do the right thing' 中的变化,但是您的用例非常简单,因此在设置表单时您可以做正确的事情。请注意,您可能希望在 Http.GET returns 之前暂停构建表格;因为那是一个异步事件;这意味着将您的表单构建逻辑放在 http 调用的闭包中。
保存按钮
对于保存按钮,您可以使用:
<button [disabled]="!(DetailForm.touched && DetailForm.valid)">
因为 DetailForm
是你的基础的变量名 FormGroup
是。
comment
表单控件在其定义中需要 [Validator.Required]
:
this.DetailForm= this.fb.group({
comment: ['', Validators.required]
});
同样重要的是要注意,您可以在创建表单并最初从服务器获取数据时创建一个 Custom Validation 以查看是否需要该评论。
如何构造表单组和表单生成器:
感谢您的更新;基于此,我将如何构建 component.ts
:
constructor(private fb: FormBuilder) { }
DetailForm: FormGroup;
ngOnInit(): void {
const dataAvailable = //this.http.get<boolean>(s => s);
if (dataAvailable) {
this.DetailForm = this.fb.group({
comment: ['', Validators.Required]
});
}
else {
this.DetailForm = this.fb.group({
comment: [''];
})
}
}
component.html
<div class="a">
<at-card *ngIf="selectedId$|async" class="b">
<at-detail [selectedDetail]="selectedDetailModel$|async">
</at-detail>
<div [formGroup]="DetailForm" class="grid grid-columns-2">
<br />
<mat-form-field>
<mat-label>Comment</mat-label>
<input matInput formControlName="comment" [type]="'text'">
</mat-form-field>
</div>
</at-card>
<at-sticky-footer>
<button [disabled]="!(DetailForm.valid && (DetailForm.touched || DetailForm.dirty)" (click)="onSubmit()">submit</button>
</at-sticky-footer>
</div>
关于 touched
和 blurred
的注释:
touched
:表示控件已经激活、改变、模糊;
dirty
:表示控件已经被激活,改变,但还没有模糊。
您需要使用哪个取决于您的用例。
我的表单输入字段是否需要根据API数据集决定。但是当它是强制性的时,我需要禁用按钮,直到用户输入一些值。我是 angular 中反应式形式的绝对初学者。需要一些专家的帮助才能做到这一点。
------------HTML---------------------
<div class="a">
<at-card *ngIf="selectedId$|async" class="b">
<at-detail [selectedDetail]="selectedDetailModel$|async">
</at-detail>
<div [formGroup]="DetailForm" class="grid grid-columns-2">
<br />
<mat-form-field>
<mat-label>Comment</mat-label>
<input matInput formControlName="comment" [type]="'text'" [required]="commentRequerd">
</mat-form-field>
</div>
</at-card>
<at-sticky-footer>
<button *ngIf="selectedId$|async" (click)="onSubmit()">submit</button>
</at-sticky-footer>
</div>
-----------------component.ts-----------------
commentRequerd: boolean;
DetailForm = new FormGroup({ comment: new FormControl(), rate: new FormControl() });
ngOnInit(): void {
inputCommentIsMandotory:boolean = <take API data about enter comment needed or not>
//accroding to that input comment filed mark as requred->
//is it requred need to check user input data to comment field ->
//if it avalable button is enable , else it disable
if(inputCommentIsMandotory){
this.commentRequerd = true;
//when user enter data button enable , if not disable(input field empty)
}else{
//alwasy button enable (input comment or not)
this.commentRequerd = false;
}
}
----------------最新更新(按钮始终禁用,即使评论不是强制性的------------ ----------------------
我像下面这样更改了代码。
isCommentMandatory(Reviews: ReviewModel[]): void {
if (Reviews.length > 0) {
console.log("called ...1 ");
this.isCommentRequired = false;
this.DetailForm = this.fb.group({
comment: [''],
rate: ['']
});
} else {
console.log("called ...2 ");
this.isCommentRequired = true;
this.DetailForm = this.fb.group({
comment: ['', Validators.required],
rate: ['']
});
}
}
并这样称呼它,
ngOnInit(): void {
this.DetailModel$.pipe().subscribe((opd => {
this.detail = opd as Detail;
const date = this.detail?.time;
const planDate = date !== undefined ? date : new Date();
//according date select reviews data
this.store.select(selectAllReviewsDetailsModel(planDate)).
subscribe(res => this.Reviews = res);
//need to call after change Details
this.isCommentMandatory(this.Reviews);
}));
}
在下面的 html 模板中,
<at-sticky-footer>
<button *ngIf="selectedId$|async" [disabled]="!(DetailModel.valid && (DetailModel.dirty))" (click)="submit()">submit</button>
</at-sticky-footer>
但是现在,这两种情况都需要输入一些内容来启用按钮。
反应式表单的想法是单向数据流。数据从组件流向模板;当用户处理完数据后,他们单击“保存”,组件再次接管。
如果需要数据验证,则在 组件中完成,如果存在更改数据的条件逻辑,则在组件中完成。如果有行为(但没有数据或验证更改),那么它是一个模板指令就可以了。 (作为 'for instance',弹出“此行已更改”视觉指示器作为突出显示在模板中作为指令非常好)。
您表单中的所有控件都是 Observable;这意味着您可以观察它们在组件和 'do the right thing' 中的变化,但是您的用例非常简单,因此在设置表单时您可以做正确的事情。请注意,您可能希望在 Http.GET returns 之前暂停构建表格;因为那是一个异步事件;这意味着将您的表单构建逻辑放在 http 调用的闭包中。
保存按钮
对于保存按钮,您可以使用:
<button [disabled]="!(DetailForm.touched && DetailForm.valid)">
因为 DetailForm
是你的基础的变量名 FormGroup
是。
comment
表单控件在其定义中需要 [Validator.Required]
:
this.DetailForm= this.fb.group({
comment: ['', Validators.required]
});
同样重要的是要注意,您可以在创建表单并最初从服务器获取数据时创建一个 Custom Validation 以查看是否需要该评论。
如何构造表单组和表单生成器:
感谢您的更新;基于此,我将如何构建 component.ts
:
constructor(private fb: FormBuilder) { }
DetailForm: FormGroup;
ngOnInit(): void {
const dataAvailable = //this.http.get<boolean>(s => s);
if (dataAvailable) {
this.DetailForm = this.fb.group({
comment: ['', Validators.Required]
});
}
else {
this.DetailForm = this.fb.group({
comment: [''];
})
}
}
component.html
<div class="a">
<at-card *ngIf="selectedId$|async" class="b">
<at-detail [selectedDetail]="selectedDetailModel$|async">
</at-detail>
<div [formGroup]="DetailForm" class="grid grid-columns-2">
<br />
<mat-form-field>
<mat-label>Comment</mat-label>
<input matInput formControlName="comment" [type]="'text'">
</mat-form-field>
</div>
</at-card>
<at-sticky-footer>
<button [disabled]="!(DetailForm.valid && (DetailForm.touched || DetailForm.dirty)" (click)="onSubmit()">submit</button>
</at-sticky-footer>
</div>
关于 touched
和 blurred
的注释:
touched
:表示控件已经激活、改变、模糊;
dirty
:表示控件已经被激活,改变,但还没有模糊。
您需要使用哪个取决于您的用例。