将 angular 2 个模型绑定到聚合物下拉列表

Bind angular 2 model to polymer dropdown

我决定这个周末花点时间看看 Angular 2 和 Polymer。我对 angular 2 非常感兴趣,并且真的很想开始用它构建一些东西。现在从 Angular 2 开始的一个缺点是还没有好的组件库。然而,由于 Angular 2 声称它应该与 Web 组件一起工作得很好,我想尝试一下 Polymer。我已经成功地将数据绑定到输入字段等简单组件。我目前所坚持的是如何将模型绑定到纸张下拉菜单的 selected 对象。由于我对两者都很陌生,所以我真的不知道该怎么做,但这是我到目前为止所尝试过的。有没有人完成将 angular 2 模型绑定到聚合物下拉菜单?

<paper-dropdown-menu  >
   <paper-menu class="dropdown-content" valueattr="id" [(ng-model)]="model">
       <paper-item *ng-for="#m of options" id="{{m.id}}" (click)="onClick()">{{m.name}}</paper-item>
   </paper-menu>
</paper-dropdown-menu>

编辑:我现在创建了一个 ValueAccessor,它似乎可以接受,但有一个例外。我尝试通过在 writeValue 方法中设置 selected 属性来使下拉列表具有预 selected 值。起初这似乎可行,但在我进行此更改后,我无法再更改 selected 值。如果我在模板中对值进行硬编码,它就会起作用,所以它似乎与 angular 和聚合物有关。我试着跟踪堆栈跟踪并比较两者之间的区别。当我对值进行硬编码时,执行 selected 的 setter 方法会触发 item-select 事件。当我在 valueAccessor 中设置 属性 时遵循相同的轨迹时,不再执行 setter 方法。似乎是 angular 2 和聚合物之间相互作用的问题。

import {Directive, ControlValueAccessor, ElementRef, Renderer, NG_VALUE_ACCESSOR, Provider, forwardRef} from "angular2/angular2"
import {isBlank, CONST_EXPR} from 'angular2/src/facade/lang';
import {setProperty} from "angular2/src/common/forms/directives/shared"

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

@Directive({
  selector: 'paper-menu[ng-model]',
  bindings: [PAPER_DROPDOWN_VALUE_ACCESSOR]
})
export class PaperDrowpdownMenuAccessor implements ControlValueAccessor {

  onChange = (_) => {};
  onTouched = () => {};

  constructor(private _renderer: Renderer, private _elementRef: ElementRef) {
    var self = this;
    this._elementRef.nativeElement.addEventListener('iron-select', function(e, v, s){
      console.log(e.target.selected);
      self.onChange(e.target.selected);
    });
  }

  writeValue(value: any): void {
    if(value){
      if(this._elementRef.nativeElement.select) {
        this._elementRef.nativeElement.select(value);
      }
      else {
        //this._elementRef.nativeElement.attributes["selected"]
        setProperty(this._renderer, this._elementRef, 'selected', value);
      }
    }       
  }

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

我终于通过实现自定义值访问器自行解决了这个问题,主要是通过查看默认值访问器是如何实现的。 https://github.com/angular/angular/blob/2.0.0-alpha.46/modules/angular2/src/common/forms/directives/default_value_accessor.ts

我对此有点纠结,因为 paper-menu 希望将预先 selected 的值设置为呈现的 html 中的属性。在我的第一次尝试中,我使用 angulars 内部 setProperty 来设置 selected 值。但是,这设置了 DOM 属性 而不是 HTML 属性,导致聚合物没有创建 get,set 属性 of selected which阻止菜单触发下拉菜单侦听的 iron-select 事件。吸取教训,记住HTML和DOM之间的区别。

import {Directive, ControlValueAccessor, ElementRef, Renderer, NG_VALUE_ACCESSOR, Provider, forwardRef} from "angular2/angular2"
import {CONST_EXPR} from 'angular2/src/facade/lang';

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

@Directive({
  selector: 'paper-menu[ng-model]',
  bindings: [PAPER_MENU_VALUE_ACCESSOR]
})
export class PaperMenuAccessor implements ControlValueAccessor {

  onChange = (_) => {};
  onTouched = () => {};

  constructor(private _renderer: Renderer, private _elementRef: ElementRef) {
    this._elementRef.nativeElement.addEventListener('iron-select', (e) => {
      this.onChange(e.target.selected);
    });
  }

  writeValue(value: any): void {
    if(this._elementRef.nativeElement.select) {
      this._elementRef.nativeElement.select(value);
    }
    else {
      this._elementRef.nativeElement.setAttribute("selected", value);
    }   
  }

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