From c7645ee59d6ee23aa50829412de774dcaa6d563b Mon Sep 17 00:00:00 2001 From: Zachary Keeton Date: Thu, 15 Jun 2017 14:12:56 -0400 Subject: [PATCH] feat(select): add compareWith Input for object value comparison (#11965) fixes #6625 --- demos/src/select/pages/page-one/page-one.html | 14 +++++++ demos/src/select/pages/page-one/page-one.ts | 32 +++++++++++++++ src/components/select/select.ts | 40 ++++++++++++++++++- 3 files changed, 85 insertions(+), 1 deletion(-) diff --git a/demos/src/select/pages/page-one/page-one.html b/demos/src/select/pages/page-one/page-one.html index e8eced2919d..966b571e2f5 100644 --- a/demos/src/select/pages/page-one/page-one.html +++ b/demos/src/select/pages/page-one/page-one.html @@ -20,6 +20,13 @@ + + Hair Color + + {{o.text}} + + + Gaming @@ -147,6 +154,13 @@ + + Skittles + + {{o.text}} + + + Disabled diff --git a/demos/src/select/pages/page-one/page-one.ts b/demos/src/select/pages/page-one/page-one.ts index 48e9ca7950c..e4bcaa81a2e 100644 --- a/demos/src/select/pages/page-one/page-one.ts +++ b/demos/src/select/pages/page-one/page-one.ts @@ -10,6 +10,10 @@ export class PageOne { petAlertOpts: any; petData: any; pets: Array; + hairColorData: any; + hairColor: any; + skittlesData: any; + skittles: Array; 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); } diff --git a/src/components/select/select.ts b/src/components/select/select.ts index 1c8f5014622..28a94b32a3a 100644 --- a/src/components/select/select.ts +++ b/src/components/select/select.ts @@ -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 + * + * Employee + * + * {{employee.name}} + * + * + * ``` + * + * ```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 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 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 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) {