web-dev-qa-db-ja.com

PrimengオートコンプリートコンポーネントのAngular2データバインディング

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属性を使用すると、UI画面にobject's valueを表示できますが、オブジェクト全体がuserIdにバインドされます。
選択したオブジェクトのuser_iduserIdにバインドするにはどうすればよいですか?

5
NTN-JAVA

私は同じ問題を抱えていて、実際には別の方法を使用して値を取得することを終了しました

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

そして実際の使用

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

@ 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

私は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イベント。

0
NTN-JAVA

これまでの質問と議論についての私の理解を要約すると、次のようになります。

  • オートコンプリートにより、ユーザーがモデルになります
  • しかし、必要なのはuser_idです
  • 基本的に、Userからuser_idへの「モデルマッピング」とその逆が必要です(モデルがuser_idで初期化されている場合、オートコンプリートで対応するユーザーを事前に選択する必要があります)

これは、オートコンプリート(および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に、またはその逆にマップする関数です。

このソリューションはおそらく他のソリューションよりも「長い」ものですが、同様のすべての状況で(オートコンプリート以外の入力コンポーネントを使用して)再利用できることに注意してください。

0
Stefan Ocke