mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-20 20:33:32 +08:00
refactor(select): using BaseInput correctly + unit tests
This commit is contained in:
@ -257,16 +257,16 @@ export const DATETIME_VALUE_ACCESSOR: any = {
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'ion-datetime',
|
selector: 'ion-datetime',
|
||||||
template:
|
template:
|
||||||
'<div *ngIf="!_text" class="datetime-text datetime-placeholder">{{placeholder}}</div>' +
|
'<div *ngIf="!_text" class="datetime-text datetime-placeholder">{{placeholder}}</div>' +
|
||||||
'<div *ngIf="_text" class="datetime-text">{{_text}}</div>' +
|
'<div *ngIf="_text" class="datetime-text">{{_text}}</div>' +
|
||||||
'<button aria-haspopup="true" ' +
|
'<button aria-haspopup="true" ' +
|
||||||
'type="button" ' +
|
'type="button" ' +
|
||||||
'[id]="id" ' +
|
'[id]="id" ' +
|
||||||
'ion-button="item-cover" ' +
|
'ion-button="item-cover" ' +
|
||||||
'[attr.aria-labelledby]="_labelId" ' +
|
'[attr.aria-labelledby]="_labelId" ' +
|
||||||
'[attr.aria-disabled]="_disabled" ' +
|
'[attr.aria-disabled]="_disabled" ' +
|
||||||
'class="item-cover">' +
|
'class="item-cover">' +
|
||||||
'</button>',
|
'</button>',
|
||||||
host: {
|
host: {
|
||||||
'[class.datetime-disabled]': '_disabled'
|
'[class.datetime-disabled]': '_disabled'
|
||||||
},
|
},
|
||||||
|
@ -145,7 +145,6 @@ export class Select extends BaseInput<string[]> implements AfterViewInit, OnDest
|
|||||||
|
|
||||||
_multi: boolean = false;
|
_multi: boolean = false;
|
||||||
_options: QueryList<Option>;
|
_options: QueryList<Option>;
|
||||||
_values: string[] = [];
|
|
||||||
_texts: string[] = [];
|
_texts: string[] = [];
|
||||||
_text: string = '';
|
_text: string = '';
|
||||||
|
|
||||||
@ -185,7 +184,7 @@ export class Select extends BaseInput<string[]> implements AfterViewInit, OnDest
|
|||||||
/**
|
/**
|
||||||
* @output {any} Emitted when the selection was cancelled.
|
* @output {any} Emitted when the selection was cancelled.
|
||||||
*/
|
*/
|
||||||
@Output() ionCancel: EventEmitter<any> = new EventEmitter();
|
@Output() ionCancel: EventEmitter<Select> = new EventEmitter();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private _app: App,
|
private _app: App,
|
||||||
@ -197,13 +196,7 @@ export class Select extends BaseInput<string[]> implements AfterViewInit, OnDest
|
|||||||
@Optional() private _nav: NavController
|
@Optional() private _nav: NavController
|
||||||
) {
|
) {
|
||||||
super(config, elementRef, renderer, 'select', form, item, null);
|
super(config, elementRef, renderer, 'select', form, item, null);
|
||||||
}
|
this._value = [];
|
||||||
|
|
||||||
/**
|
|
||||||
* @hidden
|
|
||||||
*/
|
|
||||||
ngAfterViewInit() {
|
|
||||||
this._initialize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -246,7 +239,7 @@ export class Select extends BaseInput<string[]> implements AfterViewInit, OnDest
|
|||||||
text: this.cancelText,
|
text: this.cancelText,
|
||||||
role: 'cancel',
|
role: 'cancel',
|
||||||
handler: () => {
|
handler: () => {
|
||||||
this.ionCancel.emit(null);
|
this.ionCancel.emit(this);
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
|
|
||||||
@ -369,27 +362,43 @@ export class Select extends BaseInput<string[]> implements AfterViewInit, OnDest
|
|||||||
set options(val: QueryList<Option>) {
|
set options(val: QueryList<Option>) {
|
||||||
this._options = val;
|
this._options = val;
|
||||||
|
|
||||||
if (this._values.length === 0) {
|
if (this._value.length === 0) {
|
||||||
// there are no values set at this point
|
// there are no values set at this point
|
||||||
// so check to see who should be selected
|
// so check to see who should be selected
|
||||||
this._values = val.filter(o => o.selected).map(o => o.value);
|
// we use writeValue() because we don't want to update ngModel
|
||||||
|
this.writeValue(val.filter(o => o.selected).map(o => o.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
this._inputUpdated();
|
this._inputUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_inputNormalize(val: any): string[] {
|
||||||
|
if (val === null) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
if (Array.isArray(val)) {
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
return isBlank(val) ? [] : [val];
|
||||||
|
}
|
||||||
|
|
||||||
|
_inputShouldChange(val: string[]): boolean {
|
||||||
|
if (val.length === 0 && this._value.length === 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return super._inputShouldChange(val);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hidden
|
* @hidden
|
||||||
*/
|
*/
|
||||||
_inputUpdated() {
|
_inputUpdated() {
|
||||||
const val = this.value;
|
this._texts.length = 0;
|
||||||
this._values = (Array.isArray(val) ? val : isBlank(val) ? [] : [val]);
|
|
||||||
this._texts = [];
|
|
||||||
|
|
||||||
if (this._options) {
|
if (this._options) {
|
||||||
this._options.forEach(option => {
|
this._options.forEach(option => {
|
||||||
// check this option if the option's value is in the values array
|
// check this option if the option's value is in the values array
|
||||||
option.selected = this._values.some(selectValue => {
|
option.selected = this._value.some(selectValue => {
|
||||||
return isCheckedProperty(selectValue, option.value);
|
return isCheckedProperty(selectValue, option.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
25
src/components/select/test/select.spec.ts
Normal file
25
src/components/select/test/select.spec.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
import { Select } from '../select';
|
||||||
|
import { mockApp, mockConfig, mockElementRef, mockRenderer, mockItem, mockForm } from '../../../util/mock-providers';
|
||||||
|
import { commonInputTest, BOOLEAN_CORPUS } from '../../../util/input-tester';
|
||||||
|
|
||||||
|
describe('Select', () => {
|
||||||
|
|
||||||
|
it('should pass common test', () => {
|
||||||
|
|
||||||
|
const app = mockApp();
|
||||||
|
const config = mockConfig();
|
||||||
|
const elementRef = mockElementRef();
|
||||||
|
const renderer = mockRenderer();
|
||||||
|
const item: any = mockItem();
|
||||||
|
const form = mockForm();
|
||||||
|
const select = new Select(app, form, config, elementRef, renderer, item, null);
|
||||||
|
|
||||||
|
commonInputTest(select, {
|
||||||
|
defaultValue: false,
|
||||||
|
corpus: BOOLEAN_CORPUS
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@ -119,7 +119,7 @@
|
|||||||
<br>
|
<br>
|
||||||
<code>date: {{month}}/{{year}}</code>
|
<code>date: {{month}}/{{year}}</code>
|
||||||
<br>
|
<br>
|
||||||
<code>status: {{status}}</code>
|
<code>status: {{status | json}}</code>
|
||||||
<br>
|
<br>
|
||||||
<code>currency: {{currency | json}}</code>
|
<code>currency: {{currency | json}}</code>
|
||||||
<br>
|
<br>
|
||||||
|
@ -82,8 +82,8 @@ export class PageOne {
|
|||||||
console.log('Notification select', selectedValue);
|
console.log('Notification select', selectedValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
statusChange(ev: string) {
|
statusChange(ev: any) {
|
||||||
this.status = ev;
|
this.status = ev.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
resetGender() {
|
resetGender() {
|
||||||
|
@ -126,7 +126,7 @@ export class BaseInput<T> extends Ion implements CommonInput<T> {
|
|||||||
const normalized = this._inputNormalize(val);
|
const normalized = this._inputNormalize(val);
|
||||||
const shouldUpdate = this._inputShouldChange(normalized);
|
const shouldUpdate = this._inputShouldChange(normalized);
|
||||||
if (shouldUpdate) {
|
if (shouldUpdate) {
|
||||||
console.debug('BaseInput: value has changed:', val);
|
console.debug('BaseInput: value changed:', normalized, this);
|
||||||
this._value = normalized;
|
this._value = normalized;
|
||||||
this._inputCheckHasValue(normalized);
|
this._inputCheckHasValue(normalized);
|
||||||
this._inputUpdated();
|
this._inputUpdated();
|
||||||
|
@ -52,6 +52,7 @@ export interface TestConfig {
|
|||||||
export function commonInputTest<T>(input: BaseInput<T>, config: TestConfig) {
|
export function commonInputTest<T>(input: BaseInput<T>, config: TestConfig) {
|
||||||
// TODO test form register/deregister
|
// TODO test form register/deregister
|
||||||
// TODO test item classes
|
// TODO test item classes
|
||||||
|
// TODO test disable
|
||||||
|
|
||||||
testInput(input, config, false);
|
testInput(input, config, false);
|
||||||
input.ngAfterViewInit();
|
input.ngAfterViewInit();
|
||||||
|
Reference in New Issue
Block a user