mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-18 03:00:58 +08:00
refactor(): remove checked property in favor of parent value (#19449)
BREAKING CHANGE: The following components have been updated to remove the checked or selected properties: - Radio - Segment Button - Select Developers should set the value property on the respective parent components in order to managed checked/selected status. Co-authored-by: Liam DeBeasi <liamdebeasi@users.noreply.github.com>
This commit is contained in:
@ -125,7 +125,6 @@ export class Select implements ComponentInterface {
|
||||
|
||||
@Watch('value')
|
||||
valueChanged() {
|
||||
this.updateOptions();
|
||||
this.emitStyle();
|
||||
if (this.didInit) {
|
||||
this.ionChange.emit({
|
||||
@ -135,25 +134,10 @@ export class Select implements ComponentInterface {
|
||||
}
|
||||
|
||||
async connectedCallback() {
|
||||
if (this.value === undefined) {
|
||||
if (this.multiple) {
|
||||
// there are no values set at this point
|
||||
// so check to see who should be selected
|
||||
const checked = this.childOpts.filter(o => o.selected);
|
||||
this.value = checked.map(o => getOptionValue(o));
|
||||
} else {
|
||||
const checked = this.childOpts.find(o => o.selected);
|
||||
if (checked) {
|
||||
this.value = getOptionValue(checked);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.updateOptions();
|
||||
this.updateOverlayOptions();
|
||||
this.emitStyle();
|
||||
|
||||
this.mutationO = watchForOptions<HTMLIonSelectOptionElement>(this.el, 'ion-select-option', async () => {
|
||||
this.updateOptions();
|
||||
this.updateOverlayOptions();
|
||||
});
|
||||
}
|
||||
@ -218,30 +202,32 @@ export class Select implements ComponentInterface {
|
||||
return;
|
||||
}
|
||||
const childOpts = this.childOpts;
|
||||
const value = this.value;
|
||||
switch (this.interface) {
|
||||
case 'action-sheet':
|
||||
overlay.buttons = this.createActionSheetButtons(childOpts);
|
||||
overlay.buttons = this.createActionSheetButtons(childOpts, value);
|
||||
break;
|
||||
case 'popover':
|
||||
const popover = overlay.querySelector('ion-select-popover');
|
||||
if (popover) {
|
||||
popover.options = this.createPopoverOptions(childOpts);
|
||||
popover.options = this.createPopoverOptions(childOpts, value);
|
||||
}
|
||||
break;
|
||||
case 'alert':
|
||||
const inputType = (this.multiple ? 'checkbox' : 'radio');
|
||||
overlay.inputs = this.createAlertInputs(childOpts, inputType);
|
||||
overlay.inputs = this.createAlertInputs(childOpts, inputType, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private createActionSheetButtons(data: any[]): ActionSheetButton[] {
|
||||
private createActionSheetButtons(data: HTMLIonSelectOptionElement[], selectValue: any): ActionSheetButton[] {
|
||||
const actionSheetButtons = data.map(option => {
|
||||
const value = getOptionValue(option);
|
||||
return {
|
||||
role: (option.selected ? 'selected' : ''),
|
||||
role: (isOptionSelected(value, selectValue, this.compareWith) ? 'selected' : ''),
|
||||
text: option.textContent,
|
||||
handler: () => {
|
||||
this.value = getOptionValue(option);
|
||||
this.value = value;
|
||||
}
|
||||
} as ActionSheetButton;
|
||||
});
|
||||
@ -258,38 +244,39 @@ export class Select implements ComponentInterface {
|
||||
return actionSheetButtons;
|
||||
}
|
||||
|
||||
private createAlertInputs(data: any[], inputType: string): AlertInput[] {
|
||||
return data.map(o => {
|
||||
return {
|
||||
type: inputType,
|
||||
label: o.textContent,
|
||||
value: getOptionValue(o),
|
||||
checked: o.selected,
|
||||
disabled: o.disabled
|
||||
} as AlertInput;
|
||||
});
|
||||
}
|
||||
|
||||
private createPopoverOptions(data: any[]): SelectPopoverOption[] {
|
||||
private createAlertInputs(data: HTMLIonSelectOptionElement[], inputType: 'checkbox' | 'radio', selectValue: any): AlertInput[] {
|
||||
return data.map(o => {
|
||||
const value = getOptionValue(o);
|
||||
return {
|
||||
text: o.textContent,
|
||||
type: inputType,
|
||||
label: o.textContent || '',
|
||||
value,
|
||||
checked: o.selected,
|
||||
checked: isOptionSelected(value, selectValue, this.compareWith),
|
||||
disabled: o.disabled
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
private createPopoverOptions(data: HTMLIonSelectOptionElement[], selectValue: any): SelectPopoverOption[] {
|
||||
return data.map(o => {
|
||||
const value = getOptionValue(o);
|
||||
return {
|
||||
text: o.textContent || '',
|
||||
value,
|
||||
checked: isOptionSelected(value, selectValue, this.compareWith),
|
||||
disabled: o.disabled,
|
||||
handler: () => {
|
||||
this.value = value;
|
||||
this.close();
|
||||
}
|
||||
} as SelectPopoverOption;
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
private async openPopover(ev: UIEvent) {
|
||||
const interfaceOptions = this.interfaceOptions;
|
||||
const mode = getIonMode(this);
|
||||
|
||||
const value = this.value;
|
||||
const popoverOpts: PopoverOptions = {
|
||||
mode,
|
||||
...interfaceOptions,
|
||||
@ -301,22 +288,21 @@ export class Select implements ComponentInterface {
|
||||
header: interfaceOptions.header,
|
||||
subHeader: interfaceOptions.subHeader,
|
||||
message: interfaceOptions.message,
|
||||
value: this.value,
|
||||
options: this.createPopoverOptions(this.childOpts)
|
||||
value,
|
||||
options: this.createPopoverOptions(this.childOpts, value)
|
||||
}
|
||||
};
|
||||
return popoverController.create(popoverOpts);
|
||||
}
|
||||
|
||||
private async openActionSheet() {
|
||||
|
||||
const mode = getIonMode(this);
|
||||
const interfaceOptions = this.interfaceOptions;
|
||||
const actionSheetOpts: ActionSheetOptions = {
|
||||
mode,
|
||||
...interfaceOptions,
|
||||
|
||||
buttons: this.createActionSheetButtons(this.childOpts),
|
||||
buttons: this.createActionSheetButtons(this.childOpts, this.value),
|
||||
cssClass: ['select-action-sheet', interfaceOptions.cssClass]
|
||||
};
|
||||
return actionSheetController.create(actionSheetOpts);
|
||||
@ -335,7 +321,7 @@ export class Select implements ComponentInterface {
|
||||
...interfaceOptions,
|
||||
|
||||
header: interfaceOptions.header ? interfaceOptions.header : labelText,
|
||||
inputs: this.createAlertInputs(this.childOpts, inputType),
|
||||
inputs: this.createAlertInputs(this.childOpts, inputType, this.value),
|
||||
buttons: [
|
||||
{
|
||||
text: this.cancelText,
|
||||
@ -368,23 +354,6 @@ export class Select implements ComponentInterface {
|
||||
return this.overlay.dismiss();
|
||||
}
|
||||
|
||||
private updateOptions() {
|
||||
// iterate all options, updating the selected prop
|
||||
let canSelect = true;
|
||||
const { value, childOpts, compareWith, multiple } = this;
|
||||
for (const selectOption of childOpts) {
|
||||
const optValue = getOptionValue(selectOption);
|
||||
const selected = canSelect && isOptionSelected(value, optValue, compareWith);
|
||||
selectOption.selected = selected;
|
||||
|
||||
// if current option is selected and select is single-option, we can't select
|
||||
// any option more
|
||||
if (selected && !multiple) {
|
||||
canSelect = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private getLabel() {
|
||||
return findItemLabel(this.el);
|
||||
}
|
||||
@ -490,6 +459,17 @@ export class Select implements ComponentInterface {
|
||||
}
|
||||
}
|
||||
|
||||
const isOptionSelected = (currentValue: any[] | any, compareValue: any, compareWith?: string | SelectCompareFn | null) => {
|
||||
if (currentValue === undefined) {
|
||||
return false;
|
||||
}
|
||||
if (Array.isArray(currentValue)) {
|
||||
return currentValue.some(val => compareOptions(val, compareValue, compareWith));
|
||||
} else {
|
||||
return compareOptions(currentValue, compareValue, compareWith);
|
||||
}
|
||||
};
|
||||
|
||||
const getOptionValue = (el: HTMLIonSelectOptionElement) => {
|
||||
const value = el.value;
|
||||
return (value === undefined)
|
||||
@ -507,24 +487,13 @@ const parseValue = (value: any) => {
|
||||
return value.toString();
|
||||
};
|
||||
|
||||
const isOptionSelected = (currentValue: any[] | any, compareValue: any, compareWith?: string | SelectCompareFn | null) => {
|
||||
if (currentValue === undefined) {
|
||||
return false;
|
||||
}
|
||||
if (Array.isArray(currentValue)) {
|
||||
return currentValue.some(val => compareOptions(val, compareValue, compareWith));
|
||||
} else {
|
||||
return compareOptions(currentValue, compareValue, compareWith);
|
||||
}
|
||||
};
|
||||
|
||||
const compareOptions = (currentValue: any, compareValue: any, compareWith?: string | SelectCompareFn | null): boolean => {
|
||||
if (typeof compareWith === 'function') {
|
||||
return compareWith(currentValue, compareValue);
|
||||
} else if (typeof compareWith === 'string') {
|
||||
return currentValue[compareWith] === compareValue[compareWith];
|
||||
} else {
|
||||
return currentValue === compareValue;
|
||||
return Array.isArray(compareValue) ? compareValue.includes(currentValue) : currentValue === compareValue;
|
||||
}
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user