【问题标题】:ngModel Binding on Polymer dropdown (Angular2)聚合物下拉菜单上的 ngModel 绑定(Angular2)
【发布时间】:2016-09-09 05:02:57
【问题描述】:

好的,到目前为止,我已经成功地将<paper-radio><paper-checkbox> 与 ngModel 绑定,方法是为它们中的每一个使用自定义 ControlValueAccessor。现在我被困在<paper-dropdown-menu> 这里的场景,我可以捕获paper-dropdown(iron-select)但不能绑定-two-way,即使用下面的ngModel是HTML和自定义访问器类

我的表单.html

<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));
    }
}

【问题讨论】:

    标签: angularjs typescript angular polymer polymer-1.0


    【解决方案1】:

    完整的工作示例。我没有找到将ControlValueAccessor 应用于&lt;paper-dropdown-menu&gt; 的正确方法,而是将其添加到嵌入的&lt;paper-listbox&gt; 中。唯一的缺点是,如果您对&lt;paper-dropdown-menu&gt; 使用不同的内容,您可能需要不同的ControlValueAccessor,优点是您可以将ControlValueAccessor&lt;paper-listbox&gt; 一起使用,即使它没有包含在&lt;paper-dropdown-menu&gt;

    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;
      }
    }
    
    @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

    更新

    我找到了PaperDropdownMenu 的类似答案,而不是PaperListbox Bind angular 2 model to polymer dropdown

    【讨论】:

    • 我很好奇 ngModel 是否可以将模型绑定到 &lt;paper-menu&gt; 而不是 &lt;paper-dropdown-menu&gt;,正在研究它..
    • !!...太棒了@zoechi!我已经尝试了一段时间,非常感谢!!您的 plunker 示例有效,我确实将导入修改为 beta17,因为该应用程序正在使用路由。我的主要重点是检查使用 Polymer 和 Angular2 是否明智,因为我听说这将是事实上的未来。无论如何,再次感谢!
    • 存在一些问题。当您需要将模板元素传递给 Polymer 元素或有时用于样式时,可能需要使用自定义 Polymer 元素包装 paper-xxx 元素。但总的来说它应该可以正常工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-28
    • 1970-01-01
    • 2016-11-07
    相关资源
    最近更新 更多