2017-08-03 5 views
2

私はドロップダウンを持つコントロール/テンプレート/共通のHTMLを作成する必要があります。この共通コントロールはデータサービスを呼び出し、このドロップダウンをデータとバインドします。どのようにして共通のコントロールを角度2/4で作成できますか?

私はコンポーネントを作成し、それをHTMLとしてドロップダウンし、すべての親コンポーネントのコンポーネントのセレクタを呼び出すことができます。しかし、私が欲しいのは、私はこの共通コントロールにキーを渡す必要があり、このキーはサービスに送られ、サービスは一致するレコードだけを与え、これらのレコードごとにドロップダウンはバインドされます。ここで

何私の擬似コードのコードは次のとおりです。

<div class="form-group"> 
      <label class="col-md-2 control-label">Forms</label> 
      <div class="col-md-3"> 
      COMMONCONTROL('KEY') 
      </div> 
      </div> 

角度2でこれを達成するための方法は何ですか:私はこのような何かをしたい、これに代えて

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

おかげ

答えて

2

あなただけControlValueAccessorインタフェースを実装するコンポーネントを作成し、select要素の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 
    }; 
} 

詳細情報:より良い使用方法については、私は、最初の抽象クラスを実装することをお勧め。さまざまなアクセサのimplmentationsについての情報は、角度の外観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

お返事ありがとうございました。これは私が探していたものです。このカスタムコントロールから選択したアイテムを取得する方法をもう1つ質問しますか?あなたはテンプレートで言及したvalueプロパティにアクセスする必要がありますか? –

+0

現在選択されている値にアクセスするには、いつものように 'FormControl'で' reactive-forms 'を使うか、 'のように' ngModel'にバインドします。 '。 – cyrix

+0

素晴らしい!本当にありがとう。それは私にとって、そしてそのような問題を探している人にとっては本当に役に立ちます。私はそれを確認し、答えに設定します。 –

関連する問題