Angular2 - Radio Button Binding
Solution 1:
use [value]="1" instead of value="1"
<input name="options" ng-control="options" type="radio" [value]="1" [(ngModel)]="model.options" ><br/>
<input name="options" ng-control="options" type="radio" [value]="2" [(ngModel)]="model.options" ><br/>
Edit:
As suggested by thllbrg "For angular 2.1+ use [(ngModel)]
instead of [(ng-model)]
"
Solution 2:
Note - radio button binding is now a supported feature in RC4 onwards - see this answer
Radio button example using custom RadioControlValueAccessor similar to CheckboxControlValueAccessor (Updated with Angular 2 rc-1)
App.ts
import {Component} from "@angular/core";
import {FORM_DIRECTIVES} from "@angular/common";
import {RadioControlValueAccessor} from "./radio_value_accessor";
import {bootstrap} from '@angular/platform-browser-dynamic';
@Component({
selector: "my-app",
templateUrl: "template.html",
directives: [FORM_DIRECTIVES, RadioControlValueAccessor]
})
export class App {
model;
constructor() {
this.model = {
sex: "female"
};
}
}
template.html
<div>
<form action="">
<input type="radio" [(ngModel)]="model.sex" name="sex" value="male">Male<br>
<input type="radio" [(ngModel)]="model.sex" name="sex" value="female">Female
</form>
<input type="button" value="select male" (click)="model.sex='male'">
<input type="button" value="select female" (click)="model.sex='female'">
<div>Selected Radio: {{model.sex}}</div>
</div>
radio_value_accessor.ts
import {Directive, Renderer, ElementRef, forwardRef} from '@angular/core';
import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/common';
export const RADIO_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => RadioControlValueAccessor),
multi: true
};
@Directive({
selector:
'input[type=radio][ngControl],input[type=radio][ngFormControl],input[type=radio][ngModel]',
host: {'(change)': 'onChange($event.target.value)', '(blur)': 'onTouched()'},
bindings: [RADIO_VALUE_ACCESSOR]
})
export class RadioControlValueAccessor implements ControlValueAccessor {
onChange = (_) => {};
onTouched = () => {};
constructor(private _renderer: Renderer, private _elementRef: ElementRef) {}
writeValue(value: any): void {
this._renderer.setElementProperty(this._elementRef.nativeElement, 'checked', value == this._elementRef.nativeElement.value);
}
registerOnChange(fn: (_: any) => {}): void { this.onChange = fn; }
registerOnTouched(fn: () => {}): void { this.onTouched = fn; }
}
Source : https://github.com/angular2-school/angular2-radio-button
Plunker live demo : http://plnkr.co/edit/aggee6An1iHfwsqGoE3q?p=preview
Solution 3:
My manual workaround, which involves manually updating model.options
when a new radio button is selected:
template: `
<label *ngFor="let item of radioItems">
<input type="radio" name="options" (click)="model.options = item"
[checked]="item === model.options">
{{item}}
</label>`
class App {
radioItems = 'one two three'.split(' ');
model = { options: 'two' };
}
This Plunker demonstrates the above, as well as how to use a button to change the selected radio button -- i.e., to prove that the data binding is two-way:
<button (click)="model.options = 'one'">set one</button>
Solution 4:
Here is the best way to use radio buttons in Angular2. There is no need to use the (click) event or a RadioControlValueAccessor to change the binded property value, setting [checked] property does the trick.
<input name="options" type="radio" [(ngModel)]="model.options" [value]="1"
[checked]="model.options==1" /><br/>
<input name="options" type="radio" [(ngModel)]="model.options" [value]="2"
[checked]="model.options==2" /><br/>
I published an example of using radio buttons: Angular 2: how to create radio buttons from enum and add two-way binding? It works from at least Angular 2 RC5.