Skip to content

Commit

Permalink
fix(radio): improve group/button value comparisons
Browse files Browse the repository at this point in the history
  • Loading branch information
adamdbradley committed Mar 7, 2016
1 parent 8b1783b commit 5d9b169
Show file tree
Hide file tree
Showing 5 changed files with 374 additions and 10 deletions.
16 changes: 8 additions & 8 deletions ionic/components/radio/radio-button.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {Component, Optional, Input, Output, HostListener, EventEmitter} from 'angular2/core';

import {Form} from '../../util/form';
import {isTrueProperty, isPresent, isBlank} from '../../util/util';
import {isTrueProperty, isPresent, isBlank, isCheckedProperty} from '../../util/util';
import {Item} from '../item/item';
import {ListHeader} from '../list/list';
import {RadioGroup} from './radio-group';
Expand Down Expand Up @@ -50,17 +50,17 @@ export class RadioButton {
private _checked: boolean = false;
private _disabled: boolean = false;
private _labelId: string;
private _value = null;
private _value: any = null;

/**
* @private
*/
id: string;

/**
* @output {RadioButton} expression to be evaluated when selected
* @output {any} expression to be evaluated when selected
*/
@Output() select: EventEmitter<RadioButton> = new EventEmitter();
@Output() select: EventEmitter<any> = new EventEmitter();

constructor(
private _form: Form,
Expand All @@ -87,12 +87,12 @@ export class RadioButton {
* @private
*/
@Input()
get value() {
get value(): any {
// if the value is not defined then use it's unique id
return isBlank(this._value) ? this.id : this._value;
}

set value(val) {
set value(val: any) {
this._value = val;
}

Expand Down Expand Up @@ -142,8 +142,8 @@ export class RadioButton {
* @private
*/
ngOnInit() {
if (this._group && isPresent(this._group.value) && this._group.value == this.value) {
this.checked = true;
if (this._group && isPresent(this._group.value)) {
this.checked = isCheckedProperty(this._group.value, this.value);
}
}

Expand Down
6 changes: 4 additions & 2 deletions ionic/components/radio/radio-group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {NG_VALUE_ACCESSOR} from 'angular2/common';

import {RadioButton} from './radio-button';
import {ListHeader} from '../list/list';
import {isPresent} from '../../util/util';
import {isPresent, isCheckedProperty} from '../../util/util';

const RADIO_VALUE_ACCESSOR = new Provider(
NG_VALUE_ACCESSOR, {useExisting: forwardRef(() => RadioGroup), multi: true});
Expand Down Expand Up @@ -145,16 +145,18 @@ export class RadioGroup {
*/
private _update() {
// loop through each of the radiobuttons
let hasChecked = false;
this._btns.forEach(radioButton => {

// check this radiobutton if its value is
// the same as the radiogroups value
radioButton.checked = (radioButton.value == this.value);
radioButton.checked = isCheckedProperty(this.value, radioButton.value) && !hasChecked;

if (radioButton.checked) {
// if this button is checked, then set it as
// the radiogroup's active descendant
this._setActive(radioButton);
hasChecked = true;
}
});
}
Expand Down
115 changes: 115 additions & 0 deletions ionic/components/radio/test/radio.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import {RadioGroup, RadioButton, Form} from '../../../../ionic';

export function run() {
describe('RadioGroup', () => {

describe('_update', () => {

it('should set checked via string values', () => {
let rb1 = createRadioButton();
rb1.value = 'string1';
let rb2 = createRadioButton();
rb2.value = 'string2';
let rb3 = createRadioButton();
rb3.value = 'string3';

rg.value = 'string1';
rg._update();

expect(rb1.checked).toEqual(true);
expect(rb2.checked).toEqual(false);
expect(rb3.checked).toEqual(false);
});

it('should set checked via string group value, and number button values', () => {
let rb1 = createRadioButton();
rb1.value = 1;
let rb2 = createRadioButton();
rb2.value = 2;
let rb3 = createRadioButton();
rb3.value = 3;

rg.value = '1';
rg._update();

expect(rb1.checked).toEqual(true);
expect(rb2.checked).toEqual(false);
expect(rb3.checked).toEqual(false);
});

it('should set checked via number group value, and string button values', () => {
let rb1 = createRadioButton();
rb1.value = '1';
let rb2 = createRadioButton();
rb2.value = '2';
let rb3 = createRadioButton();
rb3.value = '3';

rg.value = 1;
rg._update();

expect(rb1.checked).toEqual(true);
expect(rb2.checked).toEqual(false);
expect(rb3.checked).toEqual(false);
});

it('should set checked via empty string group value, and one empty string button value', () => {
let rb1 = createRadioButton();
rb1.value = '';
let rb2 = createRadioButton();
rb2.value = 'value2';
let rb3 = createRadioButton();
rb3.value = 'value3';

rg.value = '';
rg._update();

expect(rb1.checked).toEqual(true);
expect(rb2.checked).toEqual(false);
expect(rb3.checked).toEqual(false);
});

it('should only check at most one value', () => {
let rb1 = createRadioButton();
rb1.value = 'string1';
let rb2 = createRadioButton();
rb2.value = 'string1';
let rb3 = createRadioButton();
rb3.value = 'string1';

rg.value = 'string1';
rg._update();

expect(rb1.checked).toEqual(true);
expect(rb2.checked).toEqual(false);
expect(rb3.checked).toEqual(false);
});

});

let rg: RadioGroup;
let form: Form;

function createRadioButton() {
return new RadioButton(form, null, rg);
}

function mockRenderer(): any {
return {
setElementAttribute: function(){}
}
}

function mockElementRef(): any {
return {
nativeElement: document.createElement('div')
}
}

beforeEach(() => {
rg = new RadioGroup(mockRenderer(), mockElementRef());
form = new Form();
});

});
}
Loading

0 comments on commit 5d9b169

Please sign in to comment.