fix(select): get multiple value selects working to set selected options

also adds e2e test for multi value
This commit is contained in:
Brandy Carney
2017-12-14 18:32:37 -05:00
parent c627caba0f
commit a4dfb7ae4f
6 changed files with 244 additions and 30 deletions

View File

@ -2502,7 +2502,7 @@ declare global {
multiple?: boolean; multiple?: boolean;
interface?: string; interface?: string;
interfaceOptions?: any; interfaceOptions?: any;
value?: string|string[]; value?: string | string[];
} }
} }
} }

View File

@ -123,6 +123,9 @@ any
#### ionFocus #### ionFocus
#### ionStyle
---------------------------------------------- ----------------------------------------------

View File

@ -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: {

View File

@ -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);

View File

@ -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();
});
});
});

View File

@ -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>