2016-05-13 9 views
1

これまでのところ、<paper-radio>,<paper-checkbox>をngModelに、それぞれControlValueAccessorを使用してバインドすることに成功しました。今、私はここで<paper-dropdown-menu> シナリオにこだわって、私は紙のドロップダウンをキャプチャすることができます(鉄・セレクト)が、ngModelは、以下のHTMLとカスタムアクセサクラスngModelポリマーにバインドするドロップダウンリスト(Angular2)

で使用して、すなわち-twoウェイを結合することができない私

<paper-dropdown-menu [(ngModel)]="mymodel.selection" label="Your Fix"> 
      <paper-menu class="dropdown-content"> 
       <paper-item value="1" ngDefaultControl>Coffee</paper-item> 
       <paper-item value="2" ngDefaultControl>Cigarettes</paper-item> 
       <paper-item value="3" ngDefaultControl>Chivas</paper-item></paper-menu> 
</paper-dropdown-menu> 

そして、私のカスタムアクセサクラス

/** 
* Created by pratik on 12/5/16. 
*/ 
import { 
    Query, 
    Directive, 
    Renderer, 
    Self, 
    forwardRef, 
    Provider, 
    ElementRef, 
    QueryList 
} from 'angular2/core'; 

import {ObservableWrapper} from 'angular2/src/facade/async'; 
import {NG_VALUE_ACCESSOR, ControlValueAccessor} from 'angular2/common'; 
import {CONST_EXPR} from 'angular2/src/facade/lang'; 

const SELECT_VALUE_ACCESSOR = CONST_EXPR(new Provider(
    NG_VALUE_ACCESSOR, {useExisting: forwardRef(() => SelectControlValueAccessor), multi: true})); 

/** 
* Marks `<option>` as dynamic, so Angular can be notified when options change. 
* 
* ### Example 
* 
* ``` 
* <select ngControl="city"> 
* <option *ngFor="#c of cities" [value]="c"></option> Need to change to paper-item 
* </select> 
* ``` 
*/ 
@Directive({selector: 'option'}) // Tried changing to paper-item but still doesn't work 
export class NgSelectOption { 
} 

/** 
* The accessor for writing a value and listening to changes on a select element. 
*/ 
@Directive({ 
    selector: 'paper-dropdown-menu[ngControl],paper-dropdown-menu[ngFormControl],paper-dropdown-menu[ngModel]', 
    host: { 
     '(iron-select)': 'onChange($event.target.value)',   
     '(input)': 'onChange($event.target.value)', 
     '(blur)': 'onTouched()' 
    }, 
    bindings: [SELECT_VALUE_ACCESSOR] 
}) 
export class SelectControlValueAccessor implements ControlValueAccessor { 
    value: string; 
    onChange = (_) => {}; 
    onTouched =() => {}; 


    constructor(private _renderer: Renderer, private _elementRef: ElementRef, 
       @Query(NgSelectOption, {descendants: true}) query: QueryList<NgSelectOption>) { 
     this._updateValueWhenListOfOptionsChanges(query); 
    } 

    writeValue(value: any): void { 
     this.value = value; 
     this._renderer.setElementProperty(this._elementRef, 'value', value); 
    } 

    registerOnChange(fn:() => any): void { this.onChange = fn; } 
    registerOnTouched(fn:() => any): void { this.onTouched = fn; } 

    private _updateValueWhenListOfOptionsChanges(query: QueryList<NgSelectOption>) { 
     ObservableWrapper.subscribe(query.changes, (_) => this.writeValue(this.value)); 
    } 
} 

答えて

1

全作業例form.html。私はControlValueAccessor<paper-dropdown-menu>に適用する適切な方法を見つけられませんでしたが、代わりにそれを埋め込み<paper-listbox>に追加しました。唯一の欠点は、あなたが<paper-dropdown-menu>に異なるコンテンツを使用する場合は別のControlValueAccessorを必要とするかもしれないということです、利点は、それが<paper-dropdown-menu>

import { 
    Component, 
    Directive, 
    Renderer, 
    forwardRef, 
    Provider, 
    ElementRef, 
    ViewEncapsulation, 
} from '@angular/core'; 

import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/common'; 
const PAPER_MENU_VALUE_ACCESSOR = new Provider(
    NG_VALUE_ACCESSOR, {useExisting: forwardRef(() => PaperMenuControlValueAccessor), multi: true}); 


@Directive({ 
    selector: 'paper-listbox', 
    host: {'(iron-activate)': 'onChange($event.detail.selected)'}, 
    providers: [PAPER_MENU_VALUE_ACCESSOR] 

}) 
export class PaperMenuControlValueAccessor implements ControlValueAccessor { 
    onChange = (_:any) => { 
    }; 
    onTouched =() => { 
    }; 

    constructor(private _renderer:Renderer, private _elementRef:ElementRef) { 
    console.log('PaperMenuControlValueAccessor'); 
    } 

    writeValue(value:any):void { 
    //console.log('writeValue', value); 
    this._renderer.setElementProperty(this._elementRef.nativeElement, 'selected', value); 
    } 

    registerOnChange(fn:(_:any) => {}):void { 
    this.onChange = fn; 
    } 

    registerOnTouched(fn:() => {}):void { 
    this.onTouched = fn; 
    } 
} 
に包まれていない場合でも、あなたは <paper-listbox>ControlValueAccessorを使用することができるということです
@Component({ 
    selector: 'my-app', 
    directives: [PaperMenuControlValueAccessor], 
    encapsulation: ViewEncapsulation.None, 
    template: ` 
<h2>Hello {{name}}</h2> 

<paper-menu> 
    <paper-item>Item 1</paper-item> 
    <paper-item>Item 2</paper-item> 
</paper-menu> 


<paper-dropdown-menu label="Dinosaurs" > 
    <paper-listbox class="dropdown-content" [(ngModel)]="selected"> 
    <paper-item *ngFor="let item of items">{{item}}</paper-item> 
    </paper-listbox> 
</paper-dropdown-menu> 

<div>selected: {{items[selected]}}</div>  
    `, 
}) 
export class AppComponent { 
    items = ['allosaurus', 'brontosaurus', 'carcharodontosaurus', 'diplodocus']; 
    selected = 3; 
    name:string; 

    constructor() { 
    this.name = 'Angular2 (Release Candidate!)' 
    } 

    ngAfterViewInit() { 
    //this.selected = this.diplodocus; 
    } 
} 

Plunker example

更新

`ngModel`を探して、代わりに` <紙・ドロップダウン・メニュー> `の ` `上のモデルを結合うまくいくならば、私が代わりに好奇心 PaperListbox Bind angular 2 model to polymer dropdown

+0

イムのPaperDropdownMenuのための同様の答えを見つけましたそれに.. –

+1

!! ...ちょうど素晴らしい@zoechi!いつかの周りを試してみた。ありがとう!あなたのプランカの例がうまくいく、私はアプリケーションがルーティングを使用してbeacuse beacuseへのインポートを変更しました。私の主な焦点は、PolymerとAngular2を使用することが賢明であるかどうかをチェックすることです。とにかく再びありがとう! –

+0

いくつか問題があります。テンプレート要素をPolymer要素に渡す必要がある場合や、スタイリングのために、独自のPolymer要素でpaper-xxx要素を折り返す必要がある場合があります。しかし全体的にはうまくいくはずです。 –

関連する問題