如何在 Angular 2/4 中创建一个公共控件?
How can i create a common control in Angular 2/4?
我必须创建一个 control/template/common html,其中会有一个下拉菜单。此公共控件将调用我的数据服务并将此下拉列表与数据绑定。
我可以创建一个组件并将其 HTML 作为下拉菜单并在我的所有父组件中调用该组件的选择器。但是,我想要的是我需要将密钥传递给这个公共控件,这个密钥将被发送到服务,服务将只提供匹配的记录,并且根据这些记录,Dropdown 将被绑定。
这是我的伪代码:
<div class="form-group">
<label class="col-md-2 control-label">Forms</label>
<div class="col-md-3">
<select class="form-control">
<option value="Expression">Expression</option>
<option value="Tender">Tender</option>
<option value="Other">Other</option>
</select>
</div>
</div>
我想要的不是这个:
<div class="form-group">
<label class="col-md-2 control-label">Forms</label>
<div class="col-md-3">
COMMONCONTROL('KEY')
</div>
</div>
在angular2中有什么方法可以实现?
谢谢
您应该只创建一个实现 ControlValueAccessor
接口的组件,然后将它与 select 元素的 ngModel
连接起来。为了更好地使用,我建议先实现一个抽象 class:
import { Provider, forwardRef, Type, OpaqueToken } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
export abstract class AbstractValueAccessor implements ControlValueAccessor {
private _value: any = null;
public onChange = (_) => { };
public onTouched = () => { };
public get value(): any {
return this._value;
}
public set value(v: any) {
if (v !== this._value) {
this._value = v;
this.onChange(v);
}
}
public writeValue(value: any) {
this._value = value;
this.onChange(value);
}
public registerOnChange(fn: (_: any) => void): void {
this.onChange = fn;
}
public registerOnTouched(fn: () => void): void {
this.onTouched = fn;
}
}
export function MakeProvider(type: any) {
return {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => type),
multi: true
};
}
可以找到有关已实现的值访问器的外观和工作方式的更多信息 here. For info about the various accessor implmentations in angular look here。
然后用它扩展你的组件:
import { Component, ChangeDetectionStrategy, Input, SimpleChanges, OnChanges } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { AbstractValueAccessor, MakeProvider } from './abstract-value-accessor';
@Component({
selector: 'custom-select',
templateUrl: './custom-select.component.html',
providers: [MakeProvider(CustomSelectComponent)],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class CustomSelectComponent extends AbstractValueAccessor implements OnChanges {
private data$$ = new BehaviorSubject<any[]>([]);
@Input()
public dataKey: string;
public data$ = this.data$$.asObservable();
public get hasData$() {
return this.data$.map(data => data.length > 0);
}
constructor(private dataService: MyDataService) {
super();
}
ngOnChanges(changes: SimpleChanges) {
if(changes.dataKey && changes.dataKey.currentValue) {
this.getData(changes.dataKey.currentValue);
}
}
private getData(dataKey: string) {
this.dataService.get(dataKey).take(1).subscribe(data => this.data$$.next(data));
}
}
然后在组件的模板中将其绑定到 select:
<select [(ngModel)]="value" *ngIf="hasData$ | async">
<option [value]="option.value" *ngFor="let option of data$ | async">{{ option.name }}</option>
</select>
然后你就可以随心所欲地使用它了:
<custom-select dataKey="test"></custom-select>
注意:此代码未经测试,仅提供正确方向的方法。
我必须创建一个 control/template/common html,其中会有一个下拉菜单。此公共控件将调用我的数据服务并将此下拉列表与数据绑定。
我可以创建一个组件并将其 HTML 作为下拉菜单并在我的所有父组件中调用该组件的选择器。但是,我想要的是我需要将密钥传递给这个公共控件,这个密钥将被发送到服务,服务将只提供匹配的记录,并且根据这些记录,Dropdown 将被绑定。
这是我的伪代码:
<div class="form-group">
<label class="col-md-2 control-label">Forms</label>
<div class="col-md-3">
<select class="form-control">
<option value="Expression">Expression</option>
<option value="Tender">Tender</option>
<option value="Other">Other</option>
</select>
</div>
</div>
我想要的不是这个:
<div class="form-group">
<label class="col-md-2 control-label">Forms</label>
<div class="col-md-3">
COMMONCONTROL('KEY')
</div>
</div>
在angular2中有什么方法可以实现?
谢谢
您应该只创建一个实现 ControlValueAccessor
接口的组件,然后将它与 select 元素的 ngModel
连接起来。为了更好地使用,我建议先实现一个抽象 class:
import { Provider, forwardRef, Type, OpaqueToken } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
export abstract class AbstractValueAccessor implements ControlValueAccessor {
private _value: any = null;
public onChange = (_) => { };
public onTouched = () => { };
public get value(): any {
return this._value;
}
public set value(v: any) {
if (v !== this._value) {
this._value = v;
this.onChange(v);
}
}
public writeValue(value: any) {
this._value = value;
this.onChange(value);
}
public registerOnChange(fn: (_: any) => void): void {
this.onChange = fn;
}
public registerOnTouched(fn: () => void): void {
this.onTouched = fn;
}
}
export function MakeProvider(type: any) {
return {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => type),
multi: true
};
}
可以找到有关已实现的值访问器的外观和工作方式的更多信息 here. For info about the various accessor implmentations in angular look here。
然后用它扩展你的组件:
import { Component, ChangeDetectionStrategy, Input, SimpleChanges, OnChanges } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { AbstractValueAccessor, MakeProvider } from './abstract-value-accessor';
@Component({
selector: 'custom-select',
templateUrl: './custom-select.component.html',
providers: [MakeProvider(CustomSelectComponent)],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class CustomSelectComponent extends AbstractValueAccessor implements OnChanges {
private data$$ = new BehaviorSubject<any[]>([]);
@Input()
public dataKey: string;
public data$ = this.data$$.asObservable();
public get hasData$() {
return this.data$.map(data => data.length > 0);
}
constructor(private dataService: MyDataService) {
super();
}
ngOnChanges(changes: SimpleChanges) {
if(changes.dataKey && changes.dataKey.currentValue) {
this.getData(changes.dataKey.currentValue);
}
}
private getData(dataKey: string) {
this.dataService.get(dataKey).take(1).subscribe(data => this.data$$.next(data));
}
}
然后在组件的模板中将其绑定到 select:
<select [(ngModel)]="value" *ngIf="hasData$ | async">
<option [value]="option.value" *ngFor="let option of data$ | async">{{ option.name }}</option>
</select>
然后你就可以随心所欲地使用它了:
<custom-select dataKey="test"></custom-select>
注意:此代码未经测试,仅提供正确方向的方法。