Primeng自动完成组件的Angular2数据绑定

时间:2017-01-05 15:09:57

标签: angular primeng

使用Angular2: 2.1.0Primeng: 1.0.0
我希望Autocomplete组件绑定到我的object's key并在UI中显示object's value

这里的对象是

[{
    "user_id": 101,
    "user_name": "John"
},
{
    "user_id": 101,
    "user_name": "Ganesh"
},
{
    "user_id": 101,
    "user_name": "Irfan"
}]

app.component.html

<p-autoComplete  [(ngModel)]="userId" placeholder="User Search..." field="user_name" [suggestions]="suggestionList"  (completeMethod)="userSearch($event)"></p-autoComplete>

在自动填充中使用field属性我可以在用户界面屏幕中显示我的object's value,但整个对象绑定到userId
如何将所选对象的user_id绑定到userId

5 个答案:

答案 0 :(得分:5)

我遇到了同样的问题,实际上是使用单独的方法来捕获值

captureId(event: any) {
    this.userId = event.user_id;
}

实际使用

<p-autoComplete (onSelect)="captureId($event)" ...

答案 1 :(得分:0)

@ NTN-JAVA我已经完成了我的使用字段属性。

&#13;
&#13;
<p-autoComplete [(ngModel)]="userName" [suggestions]="filteredBrands" name="guestType"
(completeMethod)="filterBrands($event)" [size]="12" [minLength]="1" field="user_name" inputStyleClass="txt-box" placeholder="Hint: type 'v' or 'f'" [dropdown]="true" (onDropdownClick)="handleDropdownClick($event)">
 </p-autoComplete>
&#13;
&#13;
&#13;

&#13;
&#13;
  guestDetails =
    
    [{
        "user_id": 101,
        "user_name": "John"
    },
    {
        "user_id": 102,
        "user_name": "Ganesh"
    },
    {
        "user_id": 103,
        "user_name": "Irfan"
    }]

    **Javascript**
    
        handleDropdownClick() {
            this.filteredBrands = [];
            setTimeout(() => {
              this.filteredBrands = guestDetails;
              
            }, 100);
          }
&#13;
&#13;
&#13;

答案 2 :(得分:0)

我们可以简单地将primeNG的自动完成功能包装在实现ControlValueAccessor接口的自定义自动完成组件中。

如果将dataKey定义为@Input,则自定义组件将自定义数据绑定;如果未定义dataKey,则定制组件将保留primeNG的默认行为。

在以下代码中,我仅使用所需的属性和事件,但可以将其应用于primeNG API提供的所有属性和事件。

这是HTML代码:

<p-autoComplete (completeMethod)="completeMethod.emit($event)"
                (onClear)="onClear.emit($event)"
                (onDropdownClick)="onDropdownClick.emit($event)"
                (onSelect)="select($event)"
                [dataKey]="dataKey"
                [delay]="delay"
                [disabled]="disabled"
                [dropdown]="dropdown"
                [emptyMessage]="emptyMessage"
                [field]="field"
                [forceSelection]="forceSelection"
                [maxlength]="maxLength"
                [minLength]="minLength"
                [multiple]="multiple"
                [placeholder]="placeholder"
                [readonly]="readonly"
                [required]="required"
                [styleClass]="styleClass"
                [suggestions]="suggestions"
                [unique]="unique"
                [(ngModel)]="autoCompleteValue">
</p-autoComplete>

这是打字稿代码:

import { Component, EventEmitter, forwardRef, Input, Output } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

@Component({
    selector: 'mb-auto-complete',
    templateUrl: './auto-complete.component.html',
    styleUrls: ['./auto-complete.component.scss'],
    providers: [
        {
            provide: NG_VALUE_ACCESSOR,
            useExisting: forwardRef(() => AutoCompleteComponent),
            multi: true
        }
    ]
})
export class AutoCompleteComponent implements ControlValueAccessor {

    @Input() dataKey: string = null;
    @Input() delay: number = 300;
    @Input() disabled: boolean;
    @Input() dropdown: boolean = false;
    @Input() emptyMessage: string = null;
    @Input() field: any = null;
    @Input() forceSelection: boolean = null;
    @Input() maxLength: number = null;
    @Input() minLength: number = 1;
    @Input() multiple: boolean = false;
    @Input() placeholder: string;
    @Input() readonly: boolean = false;
    @Input() required: boolean = false;
    @Input() styleClass: string = null;
    @Input() suggestions: any[] = [];
    @Input() unique: boolean = true;
    @Output() completeMethod: EventEmitter<any> = new EventEmitter<any>();
    @Output() onClear: EventEmitter<any> = new EventEmitter<any>();
    @Output() onDropdownClick: EventEmitter<any> = new EventEmitter<any>();
    @Output() onSelect: EventEmitter<any> = new EventEmitter<any>();
    private onChange = (value: any): void => { /**/ };
    private onTouched = (): void => { /**/};
    public autoCompleteValue: any;

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

    public registerOnTouched(fn: any): void {
        this.onTouched = fn;
    }

    public setDisabledState(isDisabled: boolean): void {
        this.disabled = isDisabled;
    }

    public writeValue(value: any): void {
        if (this.dataKey?.length > 0) {
            this.autoCompleteValue = this.suggestions.filter((item: any) => item[this.dataKey] === value)[0];
        } else {
            this.autoCompleteValue = value;
        }
    }

    public select(selectedValue: any): void {
        const newValue: any = this.dataKey?.length > 0 ? selectedValue[this.dataKey] : selectedValue;
        this.onSelect.emit(newValue);
        this.onChange(newValue);
    }
}

然后,您可以使用自定义组件,在任何使用<p-autoComplete ..>的地方都可以将其替换为<mb-autoComplete ..>(当然,在AutoCompleteComponent的html中,必须保留{{1} }。

答案 3 :(得分:-1)

总结我对目前为止的问题和讨论的理解:

  • 自动填充功能为用户提供了模型
  • 但我们想要的是user_id
  • 基本上,我们需要一个&#34;模型映射&#34;从User到user_id以及相反的方式(如果我们的模型使用user_id初始化,则应在自动完成中预先选择相应的用户)

这可以通过包装自动完成(以及角度中的所有其他输入组件)实现的ControlValueAccessor接口以通用方式实现。这个包装器可以进行转换。 然后在包装器上使用ngModel,formControl或formControlName指令。

我创建了一个plunkr来展示这种方法。它使用&#34;国家&#34;而不是&#34;用户&#34;:

<control-value-mapper [formControl]="control" [toModel]="idOfCountry" [fromModel]="countryForId" >
      <p-autoComplete #cvDelegate

        [suggestions]="results" 
        (completeMethod)="search($event)" 
        field="name"
        dataKey="id">

      </p-autoComplete>
</control-value-mapper>

ControlValueMapper如下所示:

@Component({
  selector: 'control-value-mapper',
  template: '<ng-content></ng-content>',
  providers: [{
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(() => ControlValueMapper),
    multi: true
  }]
})
export class ControlValueMapper implements ControlValueAccessor {
  @ContentChild('cvDelegate')
  delegate: ControlValueAccessor

  @Input()
  fromModel: (any) => any;

  @Input()
  toModel: (any) => any;

  setDisabledState(isDisabled: boolean) {
    this.delegate.setDisabledState(isDisabled);
  }

  writeValue(obj: any) {
    this.delegate.writeValue(this.fromModel(obj));  
  }

  registerOnChange(fn: any)  {
    this.delegate.registerOnChange(value => fn(this.toModel(value)));
  }

  registerOnTouched(fn: any)  {
    this.delegate.registerOnTouched(value => fn(this.toModel(value)));
  }
} 

&#34; toModel&#34;和&#34; fromModel&#34;是从Country映射到其id的函数,反之亦然。

请注意,这个解决方案可能会更长一段时间。比其他人,但它可以在所有类似情况下重复使用(使用其他输入组件而不是自动完成)。

答案 4 :(得分:-1)

一年前我找到了一个解决方案,并为其他人更新了我的答案。 作为stefan's答案,我们需要模型映射,但他的答案看起来很大。

我使用了primeng自动完成组件,并使用user-search@Input()事件创建了一个名为@Output()的自有组件。

模板( user.search.component.html

<p-autoComplete [(ngModel)]="userObject" placeholder="User Search..." field="user_name" [suggestions]="userSuggesstionList"
 (onSelect)="onUserSelect($event)" (completeMethod)="search($event)">
</p-autoComplete>

组件( UserSearchComponent ),

@Component({
    selector: 'user-search',
    templateUrl: 'user.search.component.html'
})
export class UserSearchComponent implements OnInit {
   userSuggesstionList: any[] = [];
    userObject: any;
    constructor(
    ) { }

    ngOnInit() {

    }

    // note that this must be named as the input model name + "Change"
    @Output() userSelected: any = new EventEmitter();
    @Output() userIdChange: any = new EventEmitter();
    @Input()
    set userId(userId: string) {
        if (userId != null && userId != '') {
            this.userObject = // Load user object from local cache / from service.
        } else {
            this.userObject = null;
        }
    }

    get userId(): string {
        if (this.userObject != null) {
            return this.userObject.userId;
        } else {
            return null;
        }
    }

    search(event) {
        // your search logic.
    }

    onUserSelect(event) {
        this.userIdChange.emit(event.userId);
        this.userSelected.emit(event);
    }
}

用户搜索组件的用法是,

<user-search [(userId)]="user_id"></user-search>

此处作为user-search组件输入的user_id,user-search组件基于user_id从缓存/服务器加载实际用户对象。加载用户对象后,p-autocomplete将与userObject绑定,并在自动填充框中显示用户名。

从建议列表中选择用户后,将触发默认更改事件以更新父组件中的user_id值。

你也可以利用UserObject ie。 {user}中的{user_id:'xxx',user_name:'xxx'}。