我在使用反应式表单和创建自定义选择组件时遇到麻烦。
我需要创建一些自定义选择组件。
我已经查看了关于Stackoverflow的多个答案,其中涉及提供“ ControlValueAccessor”的实现。那些看起来像他们会工作,但对于我需要的东西却非常重要。
我也一直在尝试扩展“ SelectControlValueAccessor”,但这似乎不是很平常的事情。如果不常见,我会问这是否是解决问题的正确方法。
基本上,我需要一个自定义的select组件,该组件会自动进行服务调用并使用反应式表单。
这与我要执行的操作类似:
@Component({
selector: 'customer-select',
styleUrls: ['./customer-select.component.css'],
templateUrl: './customer-select.component.html'
})
export class CustomerSelectComponent extends SelectControlValueAccess implements OnInit {
customers: ICustomer[];
constructor(
private render: Renderer2,
private elementRef: ElementRef,
private customerService: CustomerService,
) {
super(render, elementRef);
}
ngOnInit(): void {
this.customerService.getCustomers()
.subscribe((response: IApiResponse<ICustomer[]>) => {
this.customers = response.Data;
this.customers.sort(this.getFuncToSortMostUsedToDefaultOrdering());
// additional logic goes here
},
(err: any) => console.log(err),
() => console.log('getCustomers() retrieved workflows')
);
}
private getCompareToStrings(firstEl: string, secondEl: string) {
if (firstEl < secondEl) {
return -1;
}
if (firstEl > secondEl) {
return 1;
}
return 0;
}
private getFuncToSortMostUsedToDefaultOrdering() {
// Assuming that we have two customers.
return (firstElement: ICustomer, secondElement: ICustomer) => {
return SomeLogicHere.Compare(firstElement, secondElement)
}
}
这是HTML代码:
<!-- Need the formControlName somehow passed in --->
<select id="customer" class="form-control" formControlName="customer">
<option *ngFor="let customer of customers" [ngValue]="customer">
{{customer.CustomerNumber}}
</option>
</select>
请随时提及我可能会遗漏的任何细节。也许是我忽略的问题或设计讨论。
也许我可以在继承上使用合成,并在仍然实现“ ControlValueAccessor”的同时编写“ SelectControlValueAccess”?
任何不涉及太多麻烦的琐碎解决方案的小问题?看起来对于此类琐碎的事情,其余解决方案是如此复杂。
编辑:之所以这样做,是因为此“客户选择”将在应用程序的很多地方使用。
此外,我将不得不为其他5个选择执行此操作,这就是为什么我不喜欢那么多琐碎的代码的原因。
编辑:
我认为,如果有人对此代码有任何输入(也许我忽略了某些内容),那么该代码就可以正常工作,请分享:永远不要破碎
@Component({
selector: 'customer-select',
templateUrl: './customer-select.component.html',
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CustomerSelectComponent),
multi: true
}
]
})
export class CustomerSelectComponent extends SelectControlValueAccessor implements OnInit {
customers: ICustomer[];
constructor(
private render: Renderer2,
private elementRef: ElementRef,
private dataService: DataService,
private fb: FormBuilder
) {
super(render, elementRef);
}
ngOnInit(): void {
this.dataService.getCustomers()
.subscribe((response: IApiResponse<ICustomer[]>) => {
this.customers = response.Data;
// Additional Logic
},
(err: any) => console.log(err),
() => console.log('getCustomers() retrieved workflows')
);
}
}
HTML:
<select id="customer" class="form-control">
<option *ngFor="let customer of customers" [ngValue]="customer">
{{customer.CustomerNumber}}
</option>
</select>
答案 0 :(得分:0)
我们在Reactive Form Control中为Bootstrap 4创建了一个自定义选择组件,该组件实现了ControlValueAccessors。这是代码,请根据您的需要进行修改。
组件:
import {
Component,
OnInit,
Input,
Output,
EventEmitter,
SimpleChanges,
forwardRef,
ElementRef,
ViewChild,
OnChanges
} from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
@Component({
selector: 'input-customselectcontrol',
templateUrl: '...',
styleUrls: ['......'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
multi: true,
useExisting: forwardRef(() => SelectFormControlComponent)
}
]
})
export class SelectCustomFormControlComponent implements OnInit, ControlValueAccessor {
@Output() dropdownEventUpdate: EventEmitter<any> = new EventEmitter();
public selectedDropDownValue = '';
@Input() dropDownListArray: Array<any>;
constructor() {}
ngOnInit() {}
writeValue(value: any) {
if (value) {
const matchObj = _.find(this.dropDownListArray, function(o) {
return o.text === value;
});
this.selectedDropDownValue = matchObj && matchObj.text ? matchObj.text : '';
}else {
this.selectedDropDownValue = 'Select';
}
}
propagateChange(time: any) {
console.log(time);
}
registerOnChange(fn) {
this.propagateChange = fn;
}
registerOnTouched() {}
// tslint:disable-next-line:use-life-cycle-interface
ngOnChanges(changes: SimpleChanges) {
}
onDropDownChange = function(id, value) {
this.selectedDropDownValue = value;
this.dropdownEventUpdate.emit({
id: id,
text: value
});
};
}
模板:
<div ngbDropdown class="d-inline-block custom-btn-color col-md px-0 w-100" #inputDropdown="ngbDropdown">
<button class="btn btn-outline-primary custom-height px-2 dropdown-custom w-100 custom-drop-down-text-override pr-4 text-left" [ngClass]="{'input-errorCls': isRequiredError}" id="sortMenu" ngbDropdownToggle>{{selectedDropDownValue}}</button>
<div ngbDropdownMenu aria-labelledby=" sortMenu" class="w-100">
<button class="dropdown-item px-3 custom-drop-down-text-override" *ngFor="let value of dropDownListArray" (click)="onDropDownChange(value.id, value.text);$event.stopPropagation();">{{value.text}}</button>
</div>
</div>
呼叫模板代码:
<input-customselectcontrol (dropdownEventUpdate)="updateTopicDropdownEvent($event, i)" [dropDownListArray]="TopicsArray" name="selectdropdownvalue" formControlName="selectdropdownvalue"></input-customselectcontrol>