mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
feat(select): add compareWith Input for object value comparison (#11965)
fixes #6625
This commit is contained in:
@@ -20,6 +20,13 @@
|
||||
</ion-select>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Hair Color</ion-label>
|
||||
<ion-select [(ngModel)]="hairColor" okText="Okay" cancelText="Dismiss" [compareWith]="compareFn">
|
||||
<ion-option *ngFor="let o of hairColorData" [value]="o">{{o.text}}</ion-option>
|
||||
</ion-select>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Gaming</ion-label>
|
||||
<ion-select [(ngModel)]="gaming" okText="Okay" cancelText="Dismiss">
|
||||
@@ -147,6 +154,13 @@
|
||||
</ion-select>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Skittles</ion-label>
|
||||
<ion-select [(ngModel)]="skittles" multiple="true" okText="Okay" cancelText="Dismiss" [compareWith]="compareFn">
|
||||
<ion-option *ngFor="let o of skittlesData" [value]="o">{{o.text}}</ion-option>
|
||||
</ion-select>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Disabled</ion-label>
|
||||
<ion-select multiple disabled="true">
|
||||
|
||||
@@ -10,6 +10,10 @@ export class PageOne {
|
||||
petAlertOpts: any;
|
||||
petData: any;
|
||||
pets: Array<string>;
|
||||
hairColorData: any;
|
||||
hairColor: any;
|
||||
skittlesData: any;
|
||||
skittles: Array<any>;
|
||||
notifications: string = 'mute_1';
|
||||
rating: number = 2;
|
||||
|
||||
@@ -31,9 +35,37 @@ export class PageOne {
|
||||
{ text: 'Honey Badger', value: 'honeybadger' },
|
||||
];
|
||||
|
||||
this.hairColorData = [
|
||||
{ text: 'Brown', value: 'brown' },
|
||||
{ text: 'Blonde', value: 'blonde' },
|
||||
{ text: 'Black', value: 'black' },
|
||||
{ text: 'Red', value: 'red' }
|
||||
];
|
||||
|
||||
// Pre-selected object with different object reference
|
||||
this.hairColor = { text: 'Brown', value: 'brown' };
|
||||
|
||||
this.skittlesData = [
|
||||
{ text: 'Red', value: 'red' },
|
||||
{ text: 'Orange', value: 'orange' },
|
||||
{ text: 'Yellow', value: 'yellow' },
|
||||
{ text: 'Green', value: 'green' },
|
||||
{ text: 'Purple', value: 'purple' }
|
||||
];
|
||||
|
||||
// Pre-selected object with different object reference
|
||||
this.skittles = [
|
||||
{ text: 'Red', value: 'red' },
|
||||
{ text: 'Purple', value: 'purple' }
|
||||
];
|
||||
|
||||
this.pets = ['cat', 'dog'];
|
||||
}
|
||||
|
||||
compareFn(option1: any, option2: any) {
|
||||
return option1.value === option2.value;
|
||||
}
|
||||
|
||||
monthChange(val: any) {
|
||||
console.log('Month Change:', val);
|
||||
}
|
||||
|
||||
@@ -123,6 +123,31 @@ import { SelectPopover, SelectPopoverOption } from './select-popover-component';
|
||||
* };
|
||||
* ```
|
||||
*
|
||||
* ### Object Value References
|
||||
*
|
||||
* When using objects for select values, it is possible for the identities of these objects to
|
||||
* change if they are coming from a server or database, while the selected value's identity
|
||||
* remains the same. For example, this can occur when an existing record with the desired object value
|
||||
* is loaded into the select, but the newly retrieved select options now have different identities. This will
|
||||
* result in the select appearing to have no value at all, even though the original selection in still intact.
|
||||
*
|
||||
* Using the `compareWith` `Input` is the solution to this problem
|
||||
*
|
||||
* ```html
|
||||
* <ion-item>
|
||||
* <ion-label>Employee</ion-label>
|
||||
* <ion-select [(ngModel)]="employee" [compareWith]="compareFn">
|
||||
* <ion-option *ngFor="let employee of employees" [value]="employee">{{employee.name}}</ion-option>
|
||||
* </ion-select>
|
||||
* </ion-item>
|
||||
* ```
|
||||
*
|
||||
* ```ts
|
||||
* compareFn(e1: Employee, e2: Employee): boolean {
|
||||
* return e1 && e2 ? e1.id === e2.id : e1 === e2;
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @demo /docs/demos/src/select/
|
||||
*/
|
||||
@Component({
|
||||
@@ -153,6 +178,7 @@ export class Select extends BaseInput<any> implements OnDestroy {
|
||||
_overlay: ActionSheet | Alert | Popover;
|
||||
_texts: string[] = [];
|
||||
_text: string = '';
|
||||
_compareWith: (o1: any, o2: any) => boolean = isCheckedProperty;
|
||||
|
||||
/**
|
||||
* @input {string} The text to display on the cancel button. Default: `Cancel`.
|
||||
@@ -187,6 +213,18 @@ export class Select extends BaseInput<any> implements OnDestroy {
|
||||
*/
|
||||
@Input() selectedText: string = '';
|
||||
|
||||
/**
|
||||
* @input {Function} The function that will be called to compare object values
|
||||
*/
|
||||
@Input()
|
||||
set compareWith(fn: (o1: any, o2: any) => boolean) {
|
||||
if (typeof fn !== 'function') {
|
||||
throw new Error(`compareWith must be a function, but received ${JSON.stringify(fn)}`);
|
||||
}
|
||||
this._compareWith = fn;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @output {any} Emitted when the selection was cancelled.
|
||||
*/
|
||||
@@ -448,7 +486,7 @@ export class Select extends BaseInput<any> implements OnDestroy {
|
||||
this._options.forEach(option => {
|
||||
// check this option if the option's value is in the values array
|
||||
option.selected = this.getValues().some(selectValue => {
|
||||
return isCheckedProperty(selectValue, option.value);
|
||||
return this._compareWith(selectValue, option.value);
|
||||
});
|
||||
|
||||
if (option.selected) {
|
||||
|
||||
Reference in New Issue
Block a user