英文:
What causes the failure to display a validation error message for radio buttons in this Angular 15 app?
问题
问题1:您做错了什么?
问题2:或者,如何默认选择性别?
问题1的答案:您的问题可能是与性别的错误关联名称有关。在您的代码中,两个性别单选按钮都绑定到同一个ngModel
变量gender
上,这可能会导致错误消息不显示。您可以为每个单选按钮使用不同的ngModel
变量来解决此问题,然后确保在表单验证中使用适当的ngModel
变量。
问题2的答案:要默认选择性别,您可以在gender
变量的初始化中指定一个默认值。例如,您可以在constructor
中添加以下行:
this.gender = 'male'; // 或者 'female',根据您想要的默认性别
这将在表单加载时自动选择默认性别。
请注意,这两个答案只是可能的解决方案之一,您可能还需要确保其他验证和表单绑定的部分都正确配置。
英文:
I have been working an app with Angular 15. I use a hand-coded JSON and JSON server to perform CRUD operations on a "employees" JSON.
I run into a problem while working on the validation of the form intended to add a new employee.
In employee-form.component.ts
I have:
import { Component } from '@angular/core';
import { Employee } from '../../models/empModel';
import { NgForm, FormGroup, Validator } from '@angular/forms';
import { HttpErrorResponse } from '@angular/common/http';
import { EmployeeService } from '../../services/employee.service';
import { EmployeeListComponent } from '../employee-list/employee-list.component';
@Component({
selector: 'app-employee-form',
templateUrl: './employee-form.component.html',
styleUrls: ['./employee-form.component.scss']
})
export class EmployeeFormComponent {
constructor(private employeeService: EmployeeService, private employeeListComponent: EmployeeListComponent) {
this.deptno = -1;
}
public empsArray: Employee[] = [];
public newEmployee: any = {}
public empno: number = 0;
public deptno: number = 0;
public firstname: string = '';
public lastname: string = '';
public gender: string = '';
public avatar: string = '';
public job: string = '';
public bio: string = '';
public skills: string = '';
public isSuccess: boolean = false;
public pickAvatar(event: any) {
let file = event.target.files[0];
this.avatar = file.name;
}
public setAvatar() {
this.newEmployee.avatar = this.avatar.length ? this.avatar : `${this.gender}.png`;
}
public doSkillsArray() {
this.newEmployee.skills = this.skills.split(',');
}
public addEmployee(form: NgForm) {
this.newEmployee = {
empno: this.empno,
deptno: this.deptno,
firstname: this.firstname,
lastname: this.lastname,
gender: this.gender,
avatar: this.avatar,
job: this.job,
bio: this.bio,
skills: this.skills
};
this.setAvatar();
this.doSkillsArray();
this.employeeService.addEmployee(this.newEmployee).subscribe(
(_response: Employee) => {
// Show success alert
this.isSuccess = true;
// Render the employee list after adding a new employee
this.employeeListComponent.getEmployees();
},
(error: HttpErrorResponse) => {
console.log(error.message);
}
);
}
}
In employee-form.component.html
I have:
<form class="modal-content" #employeeForm="ngForm" (ngSubmit)="addEmployee(employeeForm)">
<!-- Modal Header -->
<div class="modal-header py-2">
<h4 class="modal-title">New employee</h4>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<!-- Modal body -->
<div class="modal-body py-2">
<div *ngIf="isSuccess" class="text-center alert alert-success">
Employee added successfully!
</div>
<div class="position-relative mb-1">
<label class="form-label" for="firstName">First name</label>
<input type="text" class="form-control" name="firstname" id="firstName" placeholder="First name" [(ngModel)]="firstname" #first_name="ngModel" required/>
<div *ngIf="first_name.touched && first_name.errors?.['required']" class="invalid-feedback">First name is required.</div>
</div>
<div class="position-relative mb-1">
<label class="form-label" for="lastName">Last name</label>
<input type="text" class="form-control" name="lastname" id="lastName" placeholder="Last name" [(ngModel)]="lastname" #last_name="ngModel" required />
<div *ngIf="last_name.touched && last_name.errors?.['required']" class="invalid-feedback">Last name is required.</div>
</div>
<div class="position-relative mb-1">
<label class="form-label d-block" for="avatar">Photo</label>
<input type="file" class="file-upload-btn" name="avatar" id="avatar" [(ngModel)]="avatar" (change)="pickAvatar($event)">
</div>
<div class="position-relative mb-1">
<label class="form-label" for="job">Job</label>
<input type="text" class="form-control" name="job" id="job" placeholder="Job" [(ngModel)]="job" #job_title="ngModel" required />
<div *ngIf="job_title.touched && job_title.errors?.['required']" class="invalid-feedback">Job is required.</div>
</div>
<div class="position-relative mb-1">
<label class="form-label" for="job">Skills</label>
<input type="text" class="form-control" name="skills" id="skills" placeholder="Skills separated by comma" [(ngModel)]="skills"/>
</div>
<div class="position-relative mb-1">
<label class="form-label" for="department">Department</label>
<select class="form-select" name="department" id="department" [(ngModel)]="deptno" #emp_department="ngModel" required>
<option selected value="-1">Pick a department</option>
<option value="10">Management</option>
<option value="20">Sales</option>
<option value="30">Software Engineering</option>
<option value="40">Finance</option>
</select>
<div *ngIf="emp_department.touched && emp_department.value == -1" class="invalid-feedback">You must pick a department</div>
</div>
<div class="position-relative mb-0">
<label class="form-label d-block">Gender</label>
<div class="form-check form-check-inline">
<input type="radio" class="form-check-input" name="gender" id="male" value="male" [(ngModel)]="gender" #emp_gender="ngModel" required />
<label class="form-label" for="male">male</label>
</div>
<div class="form-check form-check-inline">
<input type="radio" class="form-check-input" name="gender" id="femele" value="femele" [(ngModel)]="gender" #emp_gender="ngModel" required />
<label class="form-label" for="femele">femele</label>
</div>
<div *ngIf="emp_gender.touched && emp_gender.errors?.['required']" class="invalid-feedback">You must pick a gender</div>
</div>
<div class="position-relative mb-1">
<label class="form-label" for="bio">Bio</label>
<textarea class="form-control" name="bio" id="bio" type="text" placeholder="Bio" [(ngModel)]="bio"></textarea>
</div>
</div>
<!-- Modal footer -->
<div class="modal-footer py-2">
<button type="submit" class="btn btn-success" [disabled]="!employeeForm.valid">Add employee</button>
<button type="button" class="btn btn-danger" data-bs-dismiss="modal">Cancel</button>
</div>
</form>
The problem
Even though the gender is required and the submit button remains disabled until a gender is selected, the error message "You must pick a gender" is never visible.
Questions
- What am I doing wrong?
- Alternatively, how can select a gender by default?
答案1
得分: 1
你似乎正在添加一个条件 "emp_gender.touched",该条件将限制验证,直到用户与其交互为止。
<div class="form-check form-check-inline">
<input type="radio" class="form-check-input" name="gender" id="femele" value="femele" [(ngModel)]="gender" #emp_gender="ngModel" required />
<label class="form-label" for="femele">femele</label>
</div>
<div *ngIf="emp_gender.errors?.['required']" class="invalid-feedback">You must pick a gender</div>
示例:https://stackblitz.com/edit/angular-e1jup8?file=src%2Fapp%2Fapp.component.html 您可以参考此示例以了解 touched 如何工作。
英文:
Apparently, You are adding a condition "emp_gender.touched" which will restrict validations until and unless it's been interacted with by the user.
<div class="form-check form-check-inline">
<input type="radio" class="form-check-input" name="gender" id="femele" value="femele" [(ngModel)]="gender" #emp_gender="ngModel" required />
<label class="form-label" for="femele">femele</label>
</div>
<div *ngIf="emp_gender.errors?.['required']" class="invalid-feedback">You must pick a gender</div>
Example: https://stackblitz.com/edit/angular-e1jup8?file=src%2Fapp%2Fapp.component.html You can refer to this to understand how touched works
答案2
得分: 1
以下是您提供的代码的中文翻译:
通常情况下,当输入存在错误且被触摸时,我们会显示一个错误。因此,在提交操作中,我们需要检查表单是否有效,否则标记控件为已触摸状态。
因此,我们的提交操作应该如下所示:
onSubmit(f: NgForm) {
if (f.valid)
..执行某些操作...
else
f.form.markAllAsTouched();
}
在旧版本的Angular中,我们需要遍历表单的控件:
Object.keys(f.controls).forEach(x => {
f.controls[x].markAsTouched();
});
注意:如果我们使用ReactiveForms,我们将FormGroup传递给函数,然后简单地执行以下操作:
onSubmit(f: FormGroup) {
if (f.valid)
..执行某些操作...
else
f.markAllAsTouched();
}
注意2:除了检查是否已触摸和是否存在错误之外,我们还可以基于.css采用一种不同的方法。
想象一个.html文件如下:
<input name="first" ngModel required #first="ngModel">
<div class="error">错误信息:first</div>
<input name="last" ngModel required>
<div class="error">错误信息:last</div>
我们可以使用以下方式:
input:not(.ng-invalid.ng-touched) + .error
{
display:none;
}
英文:
In general, we show an error when a input has error and when is touched. So, in submit we need check if the form is valid, else mark the controls as touched
So, our submit should be like
onSubmit(f:NgForm)
{
if (f.valid)
..do something...
else
f.form.markAllAsTouched()
}
In old versions of Angular we need loop over the controls of the form
Object.keys(f.controls).forEach(x=>{
f.controls[x].markAsTouched()
})
}
NOTE: If we are using ReactiveForms, we pass to the fucntion the FormGroup and simply
onSubmit(f:FormGroup)
{
if (f.valid)
..do something...
else
f.markAllAsTouched()
}
NOTE2: Instead of check if touched and error we can take an aproach based in .css.
Imagine a .html like
<input name="first" ngModel required #first="ngModel">
<div class="error">Error first</div>
<input name="last" ngModel required>
<div class="error">Error last</div>
We can use
input:not(.ng-invalid.ng-touched) + .error
{
display:none;
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论