Angular 2 - ラジオボタンのバインディング
Angular 2を使った形でラジオボタンを使いたい
Options : <br/>
1 : <input name="options" ng-control="options" type="radio" value="1" [(ng-model)]="model.options" ><br/>
2 : <input name="options" ng-control="options" type="radio" value="2" [(ng-model)]="model.options" ><br/>
model.optionsの初期値は1です。
ページが読み込まれるとき、最初のラジオボタンはチェックされず、変更はモデルにバインドされません。
何か案が ?
value = "1"の代わりに[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/>
編集:
Thllbrgが示唆しているように、「角度2.1+の場合は[(ngModel)]
の代わりに[(ng-model)]
を使う」
注 - ラジオボタンのバインディングは現在 サポートされている機能 RC4以降では - 参照してください この答え
CheckboxControlValueAccessorに似たカスタムRadioControlValueAccessorを使用したラジオボタンの例( 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; }
}
ソース: https://github.com/angular2-school/angular2-radio-button
プランカーライブデモ: http://plnkr.co/edit/aggee6An1iHfwsqGoE3q?p=preview
私の手動による回避策。新しいラジオボタンが選択されたときにmodel.options
を手動で更新する必要があります。
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' };
}
この Plunker 上記と、ボタンを使用して選択したラジオボタンを変更する方法、つまりデータバインディングが双方向であることを証明する方法を示します。
<button (click)="model.options = 'one'">set one</button>
これがAngular 2でラジオボタンを使用するための最良の方法です。 (click)イベントやRadioControlValueAccessorを使用してバインドされたプロパティ値を変更する必要はありません。[checked]プロパティを設定するとうまくいきます。
<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/>
ラジオボタンの使用例を公開しました。 Angular 2:enumからラジオボタンを作成して双方向バインディングを追加する方法 少なくともAngular 2 RC5から動作します。
この問題はバージョンAngular 2.0.0-rc.4で、それぞれフォームで解決されています。
Package.jsonに"@angular/forms": "0.2.0"
を含めます。
それからブートストラップをmainで拡張してください。関連する部分:
...
import { AppComponent } from './app/app.component';
import { disableDeprecatedForms, provideForms } from '@angular/forms';
bootstrap(AppComponent, [
disableDeprecatedForms(),
provideForms(),
appRouterProviders
]);
私はこれを.htmlで持っていて、完璧に動作します:value:{{buildTool}}
<form action="">
<input type="radio" [(ngModel)]="buildTool" name="buildTool" value="gradle">Gradle <br>
<input type="radio" [(ngModel)]="buildTool" name="buildTool" value="maven">Maven
</form>
これらのラジオボタンを処理する正しい方法をここで探していたのは、ここで見つけた解決策の例です。
<tr *ngFor="let entry of entries">
<td>{{ entry.description }}</td>
<td>
<input type="radio" name="radiogroup"
[value]="entry.id"
(change)="onSelectionChange(entry)">
</td>
</tr>
現在の要素をメソッドに渡す onSelectionChange に注目してください。
* ngForを使用した[value] = "item"はAngular 2および4のReactive Formsでも機能します。
<label *ngFor="let item of items">
<input type="radio" formControlName="options" [value]="item">
{{item}}
</label>`
これは私のために働く解決策です。これにはラジオボタンのバインドが含まれますが、ビジネスデータへのバインドではなく、ラジオボタンの状態へのバインドが含まれます。それはおそらく新しいプロジェクトには最善の解決策ではありませんが、私のプロジェクトには適切です。私のプロジェクトには、Angularに移植している別のテクノロジで書かれた大量の既存コードがあります。古いコードは、選択されているかどうかを確認するために各ラジオボタンを調べることに非常に関心があるというパターンに従います。解決策はクリックハンドラの解決策の変形であり、そのうちのいくつかはすでにStack Overflowで言及されています。このソリューションの付加価値は次のとおりです。
- 私が扱わなければならない古いコードのパターンで動作します。
- クリックハンドラ内の "if"文の数を減らし、ラジオボタンのグループを処理するためのヘルパークラスを作成しました。
この解決策は
- ラジオボタンごとに異なるモデルを使用する。
- ラジオボタンのモデルで "checked"属性を設定します。
- クリックされたラジオボタンのモデルをヘルパークラスに渡します。
- ヘルパークラスはモデルが最新であることを確認します。
- 「送信時」に、これは古いコードがラジオボタンの状態を調べてモデルを調べることによってどれが選択されているかを確認することを可能にします。
例:
<input type="radio"
[checked]="maleRadioButtonModel.selected"
(click)="radioButtonGroupList.selectButton(maleRadioButtonModel)"
...
<input type="radio"
[checked]="femaleRadioButtonModel.selected"
(click)="radioButtonGroupList.selectButton(femaleRadioButtonModel)"
...
ユーザーがラジオボタンをクリックすると、ヘルパークラスのselectButtonメソッドが呼び出されます。クリックされたラジオボタンのモデルを渡します。ヘルパークラスは、渡されたモデルのブール値の "selected"フィールドをtrueに設定し、他のすべてのラジオボタンモデルの "selected"フィールドをfalseに設定します。
初期化中に、コンポーネントはグループ内のすべてのラジオボタンモデルのリストを使用して、ヘルパークラスのインスタンスを構築する必要があります。この例では、 "radioButtonGroupList"は、コードが次のヘルパークラスのインスタンスになります。
import {UIButtonControlModel} from "./ui-button-control.model";
export class UIRadioButtonGroupListModel {
private readonly buttonList : UIButtonControlModel[];
private readonly debugName : string;
constructor(buttonList : UIButtonControlModel[], debugName : string) {
this.buttonList = buttonList;
this.debugName = debugName;
if (this.buttonList == null) {
throw new Error("null buttonList");
}
if (this.buttonList.length < 2) {
throw new Error("buttonList has less than 2 elements")
}
}
public selectButton(buttonToSelect : UIButtonControlModel) : void {
let foundButton : boolean = false;
for(let i = 0; i < this.buttonList.length; i++) {
let oneButton : UIButtonControlModel = this.buttonList[i];
if (oneButton === buttonToSelect) {
oneButton.selected = true;
foundButton = true;
} else {
oneButton.selected = false;
}
}
if (! foundButton) {
throw new Error("button not found in buttonList");
}
}
}
以下は私の問題を修正しました、form
タグ内にラジオ入力を追加することを検討して、値を表示するために[value]
タグを使用してください。
<form name="form" (ngSubmit)="">
<div *ngFor="let item of options">
<input [(ngModel)]="model.option_id" type="radio" name="options" [value]="item.id"> {{ item.name }}
</div>
</form>
この答えはあなたのユースケースによっては最善ではないかもしれませんが、それはうまくいきます。男性と女性の選択にラジオボタンを使う代わりに、<select> </select>
を使うことは保存と編集の両方のために完璧に働きます。
<select formControlName="gender" name="gender" class="">
<option value="M">Male</option>
<option value="F">Female</option>
</select>
FormGroupをpatchValue
と一緒に使用して編集する場合は、上記の方法で問題ありません。作成には、formControlName
の代わりに[(ngModel)]
を使用できます。まだ動作します。
ラジオボタンを使った配管作業は、代わりにselectを使うことにしました。視覚的にもUXに関しても、それは最善の方法とは言えませんが、開発者の観点からすると、はるかに簡単です。
ロードされた要素に対してクリックイベントを使用し、選択の値を関数 "getSelection"に渡してモデルを更新することによってバージョンを作成しました。
あなたのテンプレートで:
<ul>
<li *ngFor="let p of price"><input type="radio" name="price" (click)="getValue(price.value)" value="{{p}}" #price> {{p}}
</li>
</ul>
あなたのクラス:
export class App {
price:string;
price = ["1000", "2000", "3000"];
constructor() { }
model = new SomeData(this.price);
getValue(price){
this.model.price = price;
}
}
例を参照してください。 https://plnkr.co/edit/2Muje8yvWZVL9OXqG0pW?p=info
最も簡単な解決策と回避策:
<input name="toRent" type="radio" (click)="setToRentControl(false)">
<input name="toRent" type="radio" (click)="setToRentControl(true)">
setToRentControl(value){
this.vm.toRent.updateValue(value);
alert(value); //true/false
}