Skip to content

Commit

Permalink
fix(forms): radio buttons with different names should not share state
Browse files Browse the repository at this point in the history
Closes #7051
  • Loading branch information
kara committed May 25, 2016
1 parent 7a2ce7f commit 6dc88f5
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,17 @@ export class RadioControlRegistry {

select(accessor: RadioControlValueAccessor) {
this._accessors.forEach((c) => {
if (c[0].control.root === accessor._control.control.root && c[1] !== accessor) {
if (this._isSameGroup(c, accessor) && c[1] !== accessor) {
c[1].fireUncheck();
}
});
}

private _isSameGroup(controlPair:[NgControl, RadioControlValueAccessor],
accessor: RadioControlValueAccessor) {
return controlPair[0].control.root === accessor._control.control.root &&
controlPair[1].name === accessor.name;
}
}

/**
Expand Down
71 changes: 51 additions & 20 deletions modules/@angular/common/test/forms/integration_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1203,44 +1203,75 @@ export function main() {

it("should support <type=radio>",
fakeAsync(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
var t = `<form>
<input type="radio" name="food" ngControl="chicken" [(ngModel)]="data['chicken1']">
<input type="radio" name="food" ngControl="fish" [(ngModel)]="data['fish1']">
</form>
<form>
<input type="radio" name="food" ngControl="chicken" [(ngModel)]="data['chicken2']">
<input type="radio" name="food" ngControl="fish" [(ngModel)]="data['fish2']">
const t = `<form>
<input type="radio" name="food" ngControl="chicken" [(ngModel)]="data['chicken']">
<input type="radio" name="food" ngControl="fish" [(ngModel)]="data['fish']">
<input type="radio" name="food" ngControl="beef" [(ngModel)]="data['beef']">
<input type="radio" name="food" ngControl="pork" [(ngModel)]="data['pork']">
</form>`;

let fixture = tcb.overrideTemplate(MyComp8, t).createFakeAsync(MyComp8);
const fixture = tcb.overrideTemplate(MyComp8, t).createFakeAsync(MyComp8);
tick();

fixture.debugElement.componentInstance.data = {
'chicken1': new RadioButtonState(false, 'chicken'),
'fish1': new RadioButtonState(true, 'fish'),

'chicken2': new RadioButtonState(false, 'chicken'),
'fish2': new RadioButtonState(true, 'fish')
'chicken': new RadioButtonState(false, 'chicken'),
'fish': new RadioButtonState(true, 'fish'),
'beef': new RadioButtonState(false, 'beef'),
'pork': new RadioButtonState(true, 'pork')
};
fixture.detectChanges();
tick();

var input = fixture.debugElement.query(By.css("input"));
const input = fixture.debugElement.query(By.css("input"));
expect(input.nativeElement.checked).toEqual(false);

dispatchEvent(input.nativeElement, "change");
tick();

let data = fixture.debugElement.componentInstance.data;
const data = fixture.debugElement.componentInstance.data;

expect(data['chicken1']).toEqual(new RadioButtonState(true, 'chicken'));
expect(data['fish1']).toEqual(new RadioButtonState(false, 'fish'));

expect(data['chicken2']).toEqual(new RadioButtonState(false, 'chicken'));
expect(data['fish2']).toEqual(new RadioButtonState(true, 'fish'));
expect(data['chicken']).toEqual(new RadioButtonState(true, 'chicken'));
expect(data['fish']).toEqual(new RadioButtonState(false, 'fish'));
expect(data['beef']).toEqual(new RadioButtonState(false, 'beef'));
expect(data['pork']).toEqual(new RadioButtonState(false, 'pork'));
})));
});

it("should support multiple named <type=radio> groups",
fakeAsync(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
const t = `<form>
<input type="radio" name="food" ngControl="chicken" [(ngModel)]="data['chicken']">
<input type="radio" name="food" ngControl="fish" [(ngModel)]="data['fish']">
<input type="radio" name="drink" ngControl="cola" [(ngModel)]="data['cola']">
<input type="radio" name="drink" ngControl="sprite" [(ngModel)]="data['sprite']">
</form>`;

const fixture = tcb.overrideTemplate(MyComp8, t).createFakeAsync(MyComp8);
tick();

fixture.debugElement.componentInstance.data = {
'chicken': new RadioButtonState(false, 'chicken'),
'fish': new RadioButtonState(true, 'fish'),
'cola': new RadioButtonState(false, 'cola'),
'sprite': new RadioButtonState(true, 'sprite')
};
fixture.detectChanges();
tick();

const input = fixture.debugElement.query(By.css("input"));
expect(input.nativeElement.checked).toEqual(false);

dispatchEvent(input.nativeElement, "change");
tick();

const data = fixture.debugElement.componentInstance.data;

expect(data['chicken']).toEqual(new RadioButtonState(true, 'chicken'));
expect(data['fish']).toEqual(new RadioButtonState(false, 'fish'));
expect(data['cola']).toEqual(new RadioButtonState(false, 'cola'));
expect(data['sprite']).toEqual(new RadioButtonState(true, 'sprite'));
})));

describe("setting status classes", () => {
it("should work with single fields",
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
Expand Down

0 comments on commit 6dc88f5

Please sign in to comment.