使用响应式表单从angular中的下拉列表中获取选定值



我想从下拉传递硬编码值以及表单输入字段的值。我使用formControllName来获取值和控制台记录它,但我不能从下拉框中使用formControllName传递值,因为我不使用任何输入字段,所以我怎么能将值传递到。ts文件和控制台日志,以便我可以使用post api来发送该值以及其他值

模板文件

<form style="margin-left: 550px; margin-top: 100px;"  [formGroup] = 'patientForm' (submit) = 'onPatientFormSubmit()'>
<div class="row">
<div class="col-md-6">
<h1>Add Patient</h1>
<div class="mb-3">
<label for="exampleInputEmail1" class="form-label">Patient Name</label>
<input type="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" placeholder="name" formControlName="name">
</div>
<div class="mb-3">
<label for="exampleInputPassword1" class="form-label">City</label>
<input type="text" class="form-control" id="exampleInputCity1" placeholder="City" formControlName="city">
</div>
<div class="mb-3">
<label for="exampleInputPassword1" class="form-label">Illness</label>
<input type="text" class="form-control" id="exampleInputIllness1" placeholder="Illness" formControlName="illness">
</div>
<div class="dropdown mt-4" formControlName="docid">
<button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton1" data-bs-toggle="dropdown" aria-expanded="false">
Select Doctor
</button>
<ul class="dropdown-menu" aria-labelledby="dropdownMenuButton1">
<li><a class="dropdown-item">action</a></li>
<li><a class="dropdown-item">Another action</a></li>
<li><a class="dropdown-item">Something else here</a></li>
</ul>
</div>
<button type="submit" class="btn btn-primary mt-3">Submit</button>
</div>
</div>
</form>

,这是组件。ts文件

import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
@Component({
selector: 'app-add-patient',
templateUrl: './add-patient.component.html',
styleUrls: ['./add-patient.component.css']
})
export class AddPatientComponent implements OnInit {
patientForm: FormGroup;
constructor() { }
ngOnInit(): void {
this.patientForm = new FormGroup({
name: new FormControl('', [Validators.required, Validators.maxLength(20)]),
city: new FormControl('', [Validators.required, Validators.maxLength(20)]),
illness: new FormControl('', [Validators.required, Validators.maxLength(20)]),
docid: new FormControl('', [Validators.required, Validators.maxLength(20)]),
});
}
public onPatientFormSubmit(){
console.log(this.patientForm.value);
}
}

您需要创建一个具有以下特性的自定义组件:

  1. Glue:为NG_VALUE_ACCESSOR和多提供者添加提供者,以扩展现有的提供者。(参考文献1)
  2. Machinery:在组件中实现ControlValueAccessor,将自定义表单控件值与Angular响应式表单集成在一起。(参见参考文献1 &2)

解决方案

app.module.ts

import { CustomDropdownComponent } from './custom-dropdown/custom-dropdown.component';
@NgModule({
...
declarations: [..., CustomDropdownComponent],
})

add-patient.component.html

<form [formGroup]='patientForm' style="margin-left: 550px; margin-top: 100px;" (submit)='onPatientFormSubmit()'>
<div class="row">
<div class="col-md-6">
...
<app-custom-dropdown [options]="options" [class]="'mt-4'" [label]="'Select Doctor'" formControlName="docid">
</app-custom-dropdown>
</div>
</div>
</form>

add-patient.component.ts

export class AddPatientComponent implements OnInit {
options = ['action', 'Another action', 'Something else here'];
...
}

custom-dropdown.component.html

<div class="dropdown" [ngClass]="class">
<button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton1" data-bs-toggle="dropdown" aria-expanded="false">
{{ selectedOption || label  }}
</button>
<ul class="dropdown-menu" aria-labelledby="dropdownMenuButton1">
<li *ngFor="let option of options" (click)="changeSelectedOption(option)">
<a class="dropdown-item">{{option}}</a>
</li>
</ul>
</div>

custom-dropdown.component.ts

import { Component, forwardRef, Input, OnInit } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
@Component({
selector: 'app-custom-dropdown',
templateUrl: './custom-dropdown.component.html',
styleUrls: ['./custom-dropdown.component.css'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CustomDropdownComponent),
multi: true
}
]
})
export class CustomDropdownComponent implements OnInit, ControlValueAccessor {
@Input() options!: string[];
@Input() class: string | string[] | null;
@Input() label: string | null;
selectedOption: string;
constructor() {}
ngOnInit() {
}
onChange: (_: any) => {};
writeValue(value: string) {
this.selectedOption = value;
}
registerOnChange(fn: (_: any) => {}) {
this.onChange = fn;
}
changeSelectedOption(option: string) {
this.selectedOption = option;
this.onChange(option);
}
registerOnTouched() {}
}

StackBlitz的样例解决方案

引用

  1. 使用控件值访问器将您的自定义控件连接到ngModel。
  2. ControlValueAccessor
  3. Bootstrap下拉菜单作为Angular中的FormControl

最新更新