2017-08-03 35 views
2

我必須創建一個控件/模板/常見的HTML,這將有一個下拉。這個公共控件將調用我的數據服務並將此下拉列表與數據綁定。如何在Angular 2/4中創建一個通用控件?

我可以創建一個組件,並將它的HTML作爲下拉列表,並在我所有的父組件中調用該組件的選擇器。但是,我想要的是我需要將密鑰傳遞給此通用控件,並且此密鑰將被髮送到服務和服務將只給出匹配的記錄,並且根據這些記錄,下拉將會綁定。

這裏就是我的僞代碼的代碼是:

<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> 

什麼是角2實現這一目標的方法是什麼?

感謝

回答

2

你應該只創建一個實現了ControlValueAccessor接口的組件,然後將其與選擇元素的ngModel連接。爲了更好的使用我建議先實現一個抽象類:關於實現價值訪問的樣子和作品可以發現here

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中的信息。將其綁定

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 [(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> 

注意:此代碼未經測試,只提供了一個正確的方向。

+0

感謝男人的快速回復。這是我正在尋找的。還有一個查詢如何從這個自定義控件中獲取選定的項目?我應該訪問您在模板中提到的值屬性嗎? –

+0

要訪問當前選定的值,您可以像往常一樣通過'FormControl'使用'reactive-forms',或者像'一樣綁定到'ngModel' '。 – cyrix

+0

太棒了!並非常感謝你。這對我和任何正在尋找這種問題的人都會很有幫助。我會檢查它並設置爲答案。 –

相關問題