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
属性を使用すると、UI画面にobject's value
を表示できますが、オブジェクト全体がuserId
にバインドされます。
選択したオブジェクトのuser_id
をuserId
にバインドするにはどうすればよいですか?
私は同じ問題を抱えていて、実際には別の方法を使用して値を取得することを終了しました
captureId(event: any) {
this.userId = event.user_id;
}
そして実際の使用
<p-autoComplete (onSelect)="captureId($event)" ...
@ NTN-Java私はこれをusingfieldプロパティで実行しました。
<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>
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);
}
私は1年前に解決策を見つけ、他の人のために自分の答えを更新していました。 _stefan's
_の答えとして、モデルマッピングが必要ですが、彼の答えは大きなプロセスに見えます。
私はprimengオートコンプリートコンポーネントを使用し、@Input()
および@Output()
イベントを含む_user-search
_という独自のコンポーネントを作成しました。
テンプレート(ser.search.component.html)
_<p-autoComplete [(ngModel)]="userObject" placeholder="User Search..." field="user_name" [suggestions]="userSuggesstionList"
(onSelect)="onUserSelect($event)" (completeMethod)="search($event)">
</p-autoComplete>
_
コンポーネント(serSearchComponent)、
_@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を利用することもできます。 {user_id: 'xxx'、user_name: 'xxx'} in userSelected
イベント。
これまでの質問と議論についての私の理解を要約すると、次のようになります。
これは、オートコンプリート(およびAngularの他のすべての入力コンポーネント)が実装するControlValueAccessorインターフェイスをラップすることで一般的な方法で実現できます。このラッパーは変換を行うことができます。次に、ngModel、formControl、またはformControlNameディレクティブがラッパーで使用されます。
このアプローチを示すために plunkr を作成しました。 「ユーザー」の代わりに「国」を使用します。
<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)));
}
}
「toModel」と「fromModel」は、国からそのIDに、またはその逆にマップする関数です。
このソリューションはおそらく他のソリューションよりも「長い」ものですが、同様のすべての状況で(オートコンプリート以外の入力コンポーネントを使用して)再利用できることに注意してください。