使用 css 下拉框作为共享组件时如何设置和获取表单值
How to set and get form values when we use css dropdown as shared component
我有一个共享组件,它是 html 和 css 下拉列表。
我从具有不同数据的父组件调用此共享组件。
例如,我有 3 个来自父组件的共享组件实例,因此父表单组将有 3 个 formControl。由于所有 3 个表单控件现在都是共享组件。如何设置和获取所有 3 个下拉列表中的选定数据。
另外,如果要为任何下拉设置任何默认项,我们如何实现。
主要objective这里是access/get父组件表单组中的所有formControlName值。
我附上了演示代码https://stackblitz.com/edit/angular-mncdy5
正处于学习阶段,请多多指教!
您需要在共享组件中实现 ControlValueAccessors,以便您可以在父组件中将 formControls 附加到它们。这是一篇很棒的文章,它非常直接。
https://medium.com/@majdasab/implementing-control-value-accessor-in-angular-1b89f2f84ebf
这就是您的 customDropdown 组件需要如何实现 ControlValueAccessors
import { OnInit } from '@angular/core';
import { Component, forwardRef, HostBinding, Input } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
@Component({
selector: 'app-common-dropdown',
templateUrl: './common-dropdown.component.html',
styleUrls: ['./common-dropdown.component.css'],
providers: [
{ provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CommonDropdownComponent),
multi: true
}
]
})
export class CommonDropdownComponent implements ControlValueAccessor {
@Input() placeHolder: string;
@Input() dropDownId: string;
@Input() dataList: any;
onChange: any = () => {}
onTouch: any = () => {}
val= "" // this is the updated value that the class accesses
set value(val){ // this value is updated by programmatic changes if( val !== undefined && this.val !== val){
this.val = val
this.onChange(val)
this.onTouch(val)
}
constructor() { }
ngOnInit() {
}
// this method sets the value programmatically
writeValue(value: any){
this.value = value
}
registerOnChange(fn: any){
this.onChange = fn
}
registerOnTouched(fn){
this.onTouch = fn
}
propagateChange(_){
}
selectClicked(event: any) {
const ele = event.srcElement.parentNode;
ele.classList.toggle('cs-active');
}
selectedOption(ctrl: string, value: string) {
this.onChange(value) // <-- CRUCIAL need to inform formControl to update the value
document.getElementById(ctrl).innerHTML = value;
const ele = document.getElementById(ctrl).parentElement;
ele.classList.toggle('cs-active');
}
closeDropDown(event: any) {
const ele = event.srcElement;
ele.classList.remove('cs-active');
}
}
现在我们已经添加了将 formControls 附加到您的自定义组件的功能,您可以将它们添加到您的 html app.component:
<form [formGroup]="parentForm">
<app-common-dropdown placeHolder="select district" [dropDownId]="'districtLabel'" [dataList]="['bangalore','chennai','pune']" formControlName="district" ></app-common-dropdown>
<app-common-dropdown placeHolder="select distance" [dropDownId]="'distanceLabel'" [dataList]="[100,200,300,400]" formControlName="distance" ></app-common-dropdown>
<app-common-dropdown placeHolder="select state" [dropDownId]="'stateLabel'" [dataList]="['karnataka','tamil nadu','mumbai']" formControlName="state" ></app-common-dropdown>
</form>
<button type="submit" (click)="getFormValues()">submit</button>
并且您需要调整 formGroup 中的名称,因为它们与 html 表单不匹配
this.parentForm = this.fb.group({
district: ['bangalore', Validators.required], <--- SETS THE DEFAULT VALUE OF THE FORM CONTROL
distance: [''],
state:['']
});
formControlName 需要匹配 parentForm 中的 属性。
我已经更改了您的演示代码,请查看此处:https://stackblitz.com/edit/angular-sge8r3
在 CommonDropdownComponent
中,我添加了一个 Output()
,它发出从下拉列表中选择的值:
@Output() selectedValue: EventEmitter<string> = new EventEmitter<string>();
我还更改了 selectedOpiton
方法以能够发出选定的值:
selectedOption(ctrl: string, value: string) {
document.getElementById(ctrl).innerHTML = value;
const ele = document.getElementById(ctrl).parentElement;
ele.classList.toggle('cs-active');
this.selectedValue.emit(value);
}
然后在 AppComponent
中,我获取子组件发出的值并在 AppComponent
:
中设置一个变量
例如第一个下拉菜单:
<app-common-dropdown placeHolder="select district" [dropDownId]="'districtLabel'" [dataList]="['bangalore','chennai','pune']" (selectedValue)="setDistrict($event)"></app-common-dropdown>
然后在 ts
文件中我创建了一个方法 setDistrict()
:
setDistrict(value: string): void {
this.district = value;
}
您还可以在这里阅读更多关于亲子互动的内容:https://angular.io/guide/component-interaction
有多种方法可以解决这个问题。提到的@porgo 是一种方法。
请检查以下 url 以了解使用 @ViewChild
的实现
https://stackblitz.com/edit/angular-k92uxr
通信b.w组件
请参考以下url
https://angularfirebase.com/lessons/sharing-data-between-angular-components-four-methods/
我有一个共享组件,它是 html 和 css 下拉列表。 我从具有不同数据的父组件调用此共享组件。
例如,我有 3 个来自父组件的共享组件实例,因此父表单组将有 3 个 formControl。由于所有 3 个表单控件现在都是共享组件。如何设置和获取所有 3 个下拉列表中的选定数据。
另外,如果要为任何下拉设置任何默认项,我们如何实现。
主要objective这里是access/get父组件表单组中的所有formControlName值。
我附上了演示代码https://stackblitz.com/edit/angular-mncdy5 正处于学习阶段,请多多指教!
您需要在共享组件中实现 ControlValueAccessors,以便您可以在父组件中将 formControls 附加到它们。这是一篇很棒的文章,它非常直接。
https://medium.com/@majdasab/implementing-control-value-accessor-in-angular-1b89f2f84ebf
这就是您的 customDropdown 组件需要如何实现 ControlValueAccessors
import { OnInit } from '@angular/core';
import { Component, forwardRef, HostBinding, Input } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
@Component({
selector: 'app-common-dropdown',
templateUrl: './common-dropdown.component.html',
styleUrls: ['./common-dropdown.component.css'],
providers: [
{ provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CommonDropdownComponent),
multi: true
}
]
})
export class CommonDropdownComponent implements ControlValueAccessor {
@Input() placeHolder: string;
@Input() dropDownId: string;
@Input() dataList: any;
onChange: any = () => {}
onTouch: any = () => {}
val= "" // this is the updated value that the class accesses
set value(val){ // this value is updated by programmatic changes if( val !== undefined && this.val !== val){
this.val = val
this.onChange(val)
this.onTouch(val)
}
constructor() { }
ngOnInit() {
}
// this method sets the value programmatically
writeValue(value: any){
this.value = value
}
registerOnChange(fn: any){
this.onChange = fn
}
registerOnTouched(fn){
this.onTouch = fn
}
propagateChange(_){
}
selectClicked(event: any) {
const ele = event.srcElement.parentNode;
ele.classList.toggle('cs-active');
}
selectedOption(ctrl: string, value: string) {
this.onChange(value) // <-- CRUCIAL need to inform formControl to update the value
document.getElementById(ctrl).innerHTML = value;
const ele = document.getElementById(ctrl).parentElement;
ele.classList.toggle('cs-active');
}
closeDropDown(event: any) {
const ele = event.srcElement;
ele.classList.remove('cs-active');
}
}
现在我们已经添加了将 formControls 附加到您的自定义组件的功能,您可以将它们添加到您的 html app.component:
<form [formGroup]="parentForm">
<app-common-dropdown placeHolder="select district" [dropDownId]="'districtLabel'" [dataList]="['bangalore','chennai','pune']" formControlName="district" ></app-common-dropdown>
<app-common-dropdown placeHolder="select distance" [dropDownId]="'distanceLabel'" [dataList]="[100,200,300,400]" formControlName="distance" ></app-common-dropdown>
<app-common-dropdown placeHolder="select state" [dropDownId]="'stateLabel'" [dataList]="['karnataka','tamil nadu','mumbai']" formControlName="state" ></app-common-dropdown>
</form>
<button type="submit" (click)="getFormValues()">submit</button>
并且您需要调整 formGroup 中的名称,因为它们与 html 表单不匹配
this.parentForm = this.fb.group({
district: ['bangalore', Validators.required], <--- SETS THE DEFAULT VALUE OF THE FORM CONTROL
distance: [''],
state:['']
});
formControlName 需要匹配 parentForm 中的 属性。
我已经更改了您的演示代码,请查看此处:https://stackblitz.com/edit/angular-sge8r3
在 CommonDropdownComponent
中,我添加了一个 Output()
,它发出从下拉列表中选择的值:
@Output() selectedValue: EventEmitter<string> = new EventEmitter<string>();
我还更改了 selectedOpiton
方法以能够发出选定的值:
selectedOption(ctrl: string, value: string) {
document.getElementById(ctrl).innerHTML = value;
const ele = document.getElementById(ctrl).parentElement;
ele.classList.toggle('cs-active');
this.selectedValue.emit(value);
}
然后在 AppComponent
中,我获取子组件发出的值并在 AppComponent
:
例如第一个下拉菜单:
<app-common-dropdown placeHolder="select district" [dropDownId]="'districtLabel'" [dataList]="['bangalore','chennai','pune']" (selectedValue)="setDistrict($event)"></app-common-dropdown>
然后在 ts
文件中我创建了一个方法 setDistrict()
:
setDistrict(value: string): void {
this.district = value;
}
您还可以在这里阅读更多关于亲子互动的内容:https://angular.io/guide/component-interaction
有多种方法可以解决这个问题。提到的@porgo 是一种方法。
请检查以下 url 以了解使用 @ViewChild
https://stackblitz.com/edit/angular-k92uxr
通信b.w组件
请参考以下url
https://angularfirebase.com/lessons/sharing-data-between-angular-components-four-methods/