mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-24 06:22:45 +08:00
fix(select): get multiple value selects working to set selected options
also adds e2e test for multi value
This commit is contained in:
2
packages/core/src/components.d.ts
vendored
2
packages/core/src/components.d.ts
vendored
@ -2502,7 +2502,7 @@ declare global {
|
|||||||
multiple?: boolean;
|
multiple?: boolean;
|
||||||
interface?: string;
|
interface?: string;
|
||||||
interfaceOptions?: any;
|
interfaceOptions?: any;
|
||||||
value?: string|string[];
|
value?: string | string[];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -123,6 +123,9 @@ any
|
|||||||
#### ionFocus
|
#### ionFocus
|
||||||
|
|
||||||
|
|
||||||
|
#### ionStyle
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
----------------------------------------------
|
----------------------------------------------
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Component, CssClassMap, Element, Event, EventEmitter, Listen, Prop, PropDidChange, State } from '@stencil/core';
|
import { Component, CssClassMap, Element, Event, EventEmitter, Listen, Prop, PropDidChange, State } from '@stencil/core';
|
||||||
import { HTMLIonSelectOptionElementEvent } from '../select-option/select-option';
|
import { HTMLIonSelectOptionElementEvent } from '../select-option/select-option';
|
||||||
import { BlurEvent, FocusEvent, SelectInputChangeEvent } from '../../utils/input-interfaces';
|
import { BlurEvent, FocusEvent, SelectInputChangeEvent, StyleEvent } from '../../utils/input-interfaces';
|
||||||
|
|
||||||
import { ActionSheet, ActionSheetButton, ActionSheetOptions } from '../action-sheet/action-sheet';
|
import { ActionSheet, ActionSheetButton, ActionSheetOptions } from '../action-sheet/action-sheet';
|
||||||
import { Alert, AlertOptions } from '../alert/alert';
|
import { Alert, AlertOptions } from '../alert/alert';
|
||||||
@ -27,6 +27,7 @@ export class Select {
|
|||||||
private selectId: string;
|
private selectId: string;
|
||||||
private labelId: string;
|
private labelId: string;
|
||||||
private overlay: ActionSheet | Alert | Popover;
|
private overlay: ActionSheet | Alert | Popover;
|
||||||
|
private styleTmr: any;
|
||||||
|
|
||||||
@Element() private el: HTMLIonSelectElement;
|
@Element() private el: HTMLIonSelectElement;
|
||||||
|
|
||||||
@ -37,7 +38,9 @@ export class Select {
|
|||||||
@State() text: string;
|
@State() text: string;
|
||||||
|
|
||||||
@Prop({ connect: 'ion-action-sheet-controller' }) actionSheetCtrl: ActionSheetController;
|
@Prop({ connect: 'ion-action-sheet-controller' }) actionSheetCtrl: ActionSheetController;
|
||||||
|
|
||||||
@Prop({ connect: 'ion-alert-controller' }) alertCtrl: AlertController;
|
@Prop({ connect: 'ion-alert-controller' }) alertCtrl: AlertController;
|
||||||
|
|
||||||
@Prop({ connect: 'ion-popover-controller' }) popoverCtrl: PopoverController;
|
@Prop({ connect: 'ion-popover-controller' }) popoverCtrl: PopoverController;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -90,9 +93,40 @@ export class Select {
|
|||||||
@Prop() interfaceOptions: any = {};
|
@Prop() interfaceOptions: any = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* @input {string} the value of the select.
|
||||||
*/
|
*/
|
||||||
@Prop({ mutable: true }) value: string|string[];
|
@Prop({ mutable: true }) value: string | string[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emitted when the value has changed.
|
||||||
|
*/
|
||||||
|
@Event() ionChange: EventEmitter<SelectInputChangeEvent>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emitted when the selection is cancelled.
|
||||||
|
*/
|
||||||
|
@Event() ionCancel: EventEmitter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emitted when the select has focus.
|
||||||
|
*/
|
||||||
|
@Event() ionFocus: EventEmitter<FocusEvent>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emitted when the select loses focus.
|
||||||
|
*/
|
||||||
|
@Event() ionBlur: EventEmitter<BlurEvent>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @output {Event} Emitted when the styles change.
|
||||||
|
*/
|
||||||
|
@Event() ionStyle: EventEmitter<StyleEvent>;
|
||||||
|
|
||||||
|
|
||||||
|
@PropDidChange('disabled')
|
||||||
|
disabledChanged() {
|
||||||
|
this.emitStyle();
|
||||||
|
}
|
||||||
|
|
||||||
@PropDidChange('value')
|
@PropDidChange('value')
|
||||||
valueChanged() {
|
valueChanged() {
|
||||||
@ -149,41 +183,24 @@ export class Select {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Emitted when the value has changed.
|
|
||||||
*/
|
|
||||||
@Event() ionChange: EventEmitter<SelectInputChangeEvent>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Emitted when the selection is cancelled.
|
|
||||||
*/
|
|
||||||
@Event() ionCancel: EventEmitter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Emitted when the select has focus.
|
|
||||||
*/
|
|
||||||
@Event() ionFocus: EventEmitter<FocusEvent>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Emitted when the select loses focus.
|
|
||||||
*/
|
|
||||||
@Event() ionBlur: EventEmitter<BlurEvent>;
|
|
||||||
|
|
||||||
|
|
||||||
@Listen('ionSelectOptionDidLoad')
|
@Listen('ionSelectOptionDidLoad')
|
||||||
optLoad(ev: HTMLIonSelectOptionElementEvent) {
|
optLoad(ev: HTMLIonSelectOptionElementEvent) {
|
||||||
const selectOption = ev.target;
|
const selectOption = ev.target;
|
||||||
this.childOpts.push(selectOption);
|
this.childOpts.push(selectOption);
|
||||||
|
|
||||||
if (this.value !== undefined && selectOption.value === this.value) {
|
if (this.value !== undefined && (Array.isArray(this.value) && this.value.indexOf(selectOption.value) > -1) || (selectOption.value === this.value)) {
|
||||||
// this select has a value and this
|
// this select has a value and this
|
||||||
// radio equals the correct select value
|
// option equals the correct select value
|
||||||
// so let's check this select option
|
// so let's check this select option
|
||||||
selectOption.selected = true;
|
selectOption.selected = true;
|
||||||
|
|
||||||
|
} else if (Array.isArray(this.value) && this.multiple && selectOption.selected) {
|
||||||
|
// if the value is an array we need to push the option on
|
||||||
|
this.value.push(selectOption.value);
|
||||||
|
|
||||||
} else if (this.value === undefined && selectOption.selected) {
|
} else if (this.value === undefined && selectOption.selected) {
|
||||||
// this select does not have a value
|
// this select does not have a value
|
||||||
// but this selection option is checked, so let's set the
|
// but this select option is checked, so let's set the
|
||||||
// select's value from the checked select option
|
// select's value from the checked select option
|
||||||
this.value = selectOption.value;
|
this.value = selectOption.value;
|
||||||
|
|
||||||
@ -223,6 +240,7 @@ export class Select {
|
|||||||
this.value = this.multiple ? [] : undefined;
|
this.value = this.multiple ? [] : undefined;
|
||||||
}
|
}
|
||||||
this.name = this.name || this.selectId;
|
this.name = this.name || this.selectId;
|
||||||
|
this.emitStyle();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidLoad() {
|
componentDidLoad() {
|
||||||
@ -430,6 +448,16 @@ export class Select {
|
|||||||
this.ionBlur.emit();
|
this.ionBlur.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emitStyle() {
|
||||||
|
clearTimeout(this.styleTmr);
|
||||||
|
|
||||||
|
this.styleTmr = setTimeout(() => {
|
||||||
|
this.ionStyle.emit({
|
||||||
|
'select-disabled': this.disabled
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
hostData() {
|
hostData() {
|
||||||
return {
|
return {
|
||||||
class: {
|
class: {
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
<ion-item>
|
<ion-item>
|
||||||
<ion-label>Hair Color</ion-label>
|
<ion-label>Hair Color</ion-label>
|
||||||
<ion-select name="hairColor" ok-text="Okay" cancel-text="Dismiss">
|
<ion-select value="brown" name="hairColor" ok-text="Okay" cancel-text="Dismiss">
|
||||||
<ion-select-option value="brown" selected>Brown</ion-select-option>
|
<ion-select-option value="brown" selected>Brown</ion-select-option>
|
||||||
<ion-select-option value="blonde">Blonde</ion-select-option>
|
<ion-select-option value="blonde">Blonde</ion-select-option>
|
||||||
<ion-select-option value="black">Black</ion-select-option>
|
<ion-select-option value="black">Black</ion-select-option>
|
||||||
@ -186,7 +186,7 @@
|
|||||||
|
|
||||||
<ion-item>
|
<ion-item>
|
||||||
<ion-label>Pets</ion-label>
|
<ion-label>Pets</ion-label>
|
||||||
<ion-select name="pets" multiple="true">
|
<ion-select id="pets" name="pets" multiple="true">
|
||||||
<ion-select-option value="bird">Bird</ion-select-option>
|
<ion-select-option value="bird">Bird</ion-select-option>
|
||||||
<ion-select-option value="cat">Cat</ion-select-option>
|
<ion-select-option value="cat">Cat</ion-select-option>
|
||||||
<ion-select-option value="dog">Dog</ion-select-option>
|
<ion-select-option value="dog">Dog</ion-select-option>
|
||||||
@ -224,6 +224,9 @@
|
|||||||
</ion-page>
|
</ion-page>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
var pets = document.getElementById('pets');
|
||||||
|
pets.value = ['bird', 'dog'];
|
||||||
|
|
||||||
function toggleBoolean(id, prop) {
|
function toggleBoolean(id, prop) {
|
||||||
var el = document.getElementById(id);
|
var el = document.getElementById(id);
|
||||||
|
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const { By, until } = require('selenium-webdriver');
|
||||||
|
const { register, Page, platforms } = require('../../../../../scripts/e2e');
|
||||||
|
|
||||||
|
class E2ETestPage extends Page {
|
||||||
|
constructor(driver, platform) {
|
||||||
|
super(driver, `http://localhost:3333/src/components/select/test/multiple-value?ionicplatform=${platform}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
present(buttonId) {
|
||||||
|
this.navigate();
|
||||||
|
this.driver.findElement(By.id(buttonId)).click();
|
||||||
|
this.driver.wait(until.elementLocated(By.css('.select-wrapper')));
|
||||||
|
return this.driver.wait(until.elementIsVisible(this.driver.findElement(By.css('.select-wrapper'))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
platforms.forEach(platform => {
|
||||||
|
describe('select/multiple-value', () => {
|
||||||
|
register('should init', driver => {
|
||||||
|
const page = new E2ETestPage(driver, platform);
|
||||||
|
return page.navigate();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,153 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html dir="ltr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Select - Multiple Value</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||||
|
<script src="/dist/ionic.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<ion-app>
|
||||||
|
<ion-page>
|
||||||
|
<ion-header>
|
||||||
|
<ion-toolbar>
|
||||||
|
<ion-title>Select - Multiple Value</ion-title>
|
||||||
|
</ion-toolbar>
|
||||||
|
</ion-header>
|
||||||
|
|
||||||
|
<ion-content class="outer-content test-content">
|
||||||
|
|
||||||
|
<ion-item>
|
||||||
|
<ion-label>Toppings</ion-label>
|
||||||
|
<ion-select id="toppings" multiple="true" cancel-text="Nah" ok-text="Okay!">
|
||||||
|
<ion-select-option value="bacon">Bacon</ion-select-option>
|
||||||
|
<ion-select-option value="olives">Black Olives</ion-select-option>
|
||||||
|
<ion-select-option value="xcheese">Extra Cheese</ion-select-option>
|
||||||
|
<ion-select-option value="peppers">Green Peppers</ion-select-option>
|
||||||
|
<ion-select-option value="mushrooms">Mushrooms</ion-select-option>
|
||||||
|
<ion-select-option value="onions">Onions</ion-select-option>
|
||||||
|
<ion-select-option value="pepperoni">Pepperoni</ion-select-option>
|
||||||
|
<ion-select-option value="pineapple">Pineapple</ion-select-option>
|
||||||
|
<ion-select-option value="sausage">Sausage</ion-select-option>
|
||||||
|
<ion-select-option value="Spinach">Spinach</ion-select-option>
|
||||||
|
</ion-select>
|
||||||
|
</ion-item>
|
||||||
|
|
||||||
|
<ion-item>
|
||||||
|
<ion-label>Car Features</ion-label>
|
||||||
|
<ion-select id="carFeatures" multiple="true">
|
||||||
|
<ion-select-option value="backupcamera">Backup Camera</ion-select-option>
|
||||||
|
<ion-select-option value="heatedseats">Headted Seats</ion-select-option>
|
||||||
|
<ion-select-option value="keyless">Keyless Entry</ion-select-option>
|
||||||
|
<ion-select-option value="navigation">Navigation</ion-select-option>
|
||||||
|
<ion-select-option value="parkingassist">Parking Assist</ion-select-option>
|
||||||
|
<ion-select-option value="sunroof">Sun Roof</ion-select-option>
|
||||||
|
</ion-select>
|
||||||
|
</ion-item>
|
||||||
|
|
||||||
|
<ion-item>
|
||||||
|
<ion-label>Pets</ion-label>
|
||||||
|
<ion-select id="pets" multiple>
|
||||||
|
<ion-select-option value="cat">Cat</ion-select-option>
|
||||||
|
<ion-select-option value="dog">Dog</ion-select-option>
|
||||||
|
<ion-select-option value="turtle">Turtle</ion-select-option>
|
||||||
|
<ion-select-option value="fish">Fish</ion-select-option>
|
||||||
|
</ion-select>
|
||||||
|
</ion-item>
|
||||||
|
|
||||||
|
<ion-item>
|
||||||
|
<ion-label>Disabled</ion-label>
|
||||||
|
<ion-select id="disabled" multiple disabled>
|
||||||
|
<ion-select-option selected="true">Selected Text</ion-select-option>
|
||||||
|
</ion-select>
|
||||||
|
</ion-item>
|
||||||
|
|
||||||
|
<ion-item>
|
||||||
|
<ion-label>Statuses</ion-label>
|
||||||
|
<ion-select id="status" multiple>
|
||||||
|
<ion-select-option value="selected" selected="true">Selected</ion-select-option>
|
||||||
|
<ion-select-option value="default" selected>Default</ion-select-option>
|
||||||
|
<ion-select-option value="disabled" disabled="true">Disabled</ion-select-option>
|
||||||
|
</ion-select>
|
||||||
|
</ion-item>
|
||||||
|
|
||||||
|
<p aria-hidden="true" padding>
|
||||||
|
<code>toppings: <span id="toppingsResults"></span></code><br>
|
||||||
|
<code>carFeatures: <span id="carFeaturesResults"></span></code><br>
|
||||||
|
<code>pets: <span id="petsResults"></span></code><br>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<form>
|
||||||
|
<ion-list padding-vertical>
|
||||||
|
<ion-item>
|
||||||
|
<ion-input type="text"></ion-input>
|
||||||
|
</ion-item>
|
||||||
|
<ion-item>
|
||||||
|
<ion-label>Select</ion-label>
|
||||||
|
<ion-select multiple="true">
|
||||||
|
<ion-select-option selected>1</ion-select-option>
|
||||||
|
<ion-select-option>2</ion-select-option>
|
||||||
|
<ion-select-option selected>3</ion-select-option>
|
||||||
|
</ion-select>
|
||||||
|
</ion-item>
|
||||||
|
<ion-button expand="block" type="submit">Submit</ion-button>
|
||||||
|
</ion-list>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<ion-item>
|
||||||
|
<ion-label floating>Floating label</ion-label>
|
||||||
|
<ion-select multiple="true">
|
||||||
|
<ion-select-option value="bacon">Bacon</ion-select-option>
|
||||||
|
<ion-select-option value="olives">Black Olives</ion-select-option>
|
||||||
|
<ion-select-option value="xcheese">Extra Cheese</ion-select-option>
|
||||||
|
<ion-select-option value="peppers">Green Peppers</ion-select-option>
|
||||||
|
<ion-select-option value="mushrooms">Mushrooms</ion-select-option>
|
||||||
|
<ion-select-option value="onions">Onions</ion-select-option>
|
||||||
|
<ion-select-option value="pepperoni">Pepperoni</ion-select-option>
|
||||||
|
<ion-select-option value="pineapple">Pineapple</ion-select-option>
|
||||||
|
<ion-select-option value="sausage">Sausage</ion-select-option>
|
||||||
|
<ion-select-option value="Spinach">Spinach</ion-select-option>
|
||||||
|
</ion-select>
|
||||||
|
</ion-item>
|
||||||
|
|
||||||
|
</ion-content>
|
||||||
|
</ion-page>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
var toppings = document.getElementById('toppings');
|
||||||
|
toppings.value = ['bacon', 'xcheese'];
|
||||||
|
|
||||||
|
var carFeatures = document.getElementById('carFeatures');
|
||||||
|
|
||||||
|
var pets = document.getElementById('pets');
|
||||||
|
pets.value = ['cat', 'dog'];
|
||||||
|
|
||||||
|
setResults(toppings);
|
||||||
|
setResults(carFeatures);
|
||||||
|
setResults(pets);
|
||||||
|
|
||||||
|
toppings.addEventListener('ionChange', function(ev) {
|
||||||
|
setResults(toppings);
|
||||||
|
});
|
||||||
|
carFeatures.addEventListener('ionChange', function(ev) {
|
||||||
|
setResults(carFeatures);
|
||||||
|
});
|
||||||
|
pets.addEventListener('ionChange', function(ev) {
|
||||||
|
setResults(pets);
|
||||||
|
});
|
||||||
|
|
||||||
|
function setResults(select) {
|
||||||
|
if (select.id) {
|
||||||
|
var resultsEl = document.getElementById(select.id + 'Results');
|
||||||
|
if (resultsEl) {
|
||||||
|
resultsEl.innerHTML = select.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</ion-app>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
|
|
||||||
|
|
Reference in New Issue
Block a user