使用Angular2: 2.1.0
和Primeng: 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
?
答案 0 :(得分:5)
我遇到了同样的问题,实际上是使用单独的方法来捕获值
captureId(event: any) {
this.userId = event.user_id;
}
实际使用
<p-autoComplete (onSelect)="captureId($event)" ...
答案 1 :(得分:0)
@ NTN-JAVA我已经完成了我的使用字段属性。
<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;
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;
答案 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)
总结我对目前为止的问题和讨论的理解:
这可以通过包装自动完成(以及角度中的所有其他输入组件)实现的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'}。