使用ControlValueAccessor(FormGroup / FormControl)选择不正确的单选按钮值

时间:2017-06-28 14:39:20

标签: angular angular2-template angular2-forms

我无法正确选择单选按钮&呆在那里。

1)它不记得它的价值并留在那里   2)它被取消选中并跳转到不同的单选按钮组。

制作。

1)选择性别(有效)。   2)选择一种食物(性别未被选中,饮料被错误地选中但食物被正确选择)

[App.ts]

import { Component, NgModule } from '@angular/core';
import { FormGroup, FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms';
import { BrowserModule }  from '@angular/platform-browser';

import { HtmlRadio1, IHtmlRadioOption1 } from './src1/HtmlRadio1';

@Component({
    moduleId: module.id,  
    selector: 'app',
    templateUrl: 'App.template.html'
})
export class App {
    _genderOptions: IHtmlRadioOption1[] = <IHtmlRadioOption1[]>[
        <IHtmlRadioOption1>{ value: 'M', label: 'Male' },
        <IHtmlRadioOption1>{ value: 'F', label: 'Female' },
        <IHtmlRadioOption1>{ value: 'N', label: 'Neuter' }
    ];
    _foodOptions: IHtmlRadioOption1[] = <IHtmlRadioOption1[]>[
        <IHtmlRadioOption1>{ value: '0', label: 'Apple' },
        <IHtmlRadioOption1>{ value: '1', label: 'Banana' },
        <IHtmlRadioOption1>{ value: '2', label: 'Bread' }
    ];
    _drinkOptions: IHtmlRadioOption1[] = <IHtmlRadioOption1[]>[
        <IHtmlRadioOption1>{ value: '0', label: 'Coke' },
        <IHtmlRadioOption1>{ value: '1', label: 'Milk' },
        <IHtmlRadioOption1>{ value: '2', label: 'Coffee' }
    ];

    _form: FormGroup = new FormGroup({
        gender: new FormControl(),
        food: new FormControl(),
        drink: new FormControl()
    });
}

@NgModule({
    declarations: [App, HtmlRadio1],
    entryComponents: [App, HtmlRadio1],
    imports: [FormsModule, ReactiveFormsModule, BrowserModule],
    bootstrap: [App, HtmlRadio1]
})
export class TestModule {
}

[App.template.html]

<form [formGroup]="_form">
    <div>
        <span>Gender</span>
        <span><htmlRadio1 formControlName="gender" [options]="_genderOptions"></htmlRadio1></span>
    </div>
    <div>
        <span>Food</span>
        <span><htmlRadio1 formControlName="food" [options]="_foodOptions"></htmlRadio1></span>
    </div>
    <div>
        <span>Drink</span>
        <span><htmlRadio1 formControlName="drink" [options]="_drinkOptions"></htmlRadio1></span>
    </div>
</form>

[HtmlRadio1.ts]

import { Component, Input, forwardRef, ViewChild } from '@angular/core';
import { NG_VALUE_ACCESSOR, NgControl, ControlValueAccessor } from '@angular/forms';

const CONTROL_VALUE_ACCESSOR = { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => HtmlRadio1), multi: true };

export class HtmlInput1 implements ControlValueAccessor {
    private _value: string;
    get value(): string {
        return this._value;
    }
    @Input() set value(val: string) {
        this._value = val;
        this.onChange(val);
    }
    onChange = (_: any) => { };
    onTouched = () => { };
    registerOnChange(fn: (_: any) => void): void { this.onChange = fn; }
    registerOnTouched(fn: () => void): void { this.onTouched = fn; }
    writeValue(obj: any): void {
        this.value = obj;
        //this.ngModel.valueAccessor.writeValue(obj);
    }
    protected ngModel: NgControl;

    /** @internal */
    inputId = 'designer_' + Math.random().toString().substr(2);
}
export interface IHtmlRadioOption1 {
    label: string;
    value: string;
}

@Component({
    selector: 'htmlRadio1',
    moduleId: module.id,
    templateUrl: 'HtmlRadio1.template.html',
    providers: [CONTROL_VALUE_ACCESSOR]
})
export class HtmlRadio1 extends HtmlInput1 {
    @ViewChild(NgControl) set ngControl(value: NgControl) { this.ngModel = value; }

    @Input('options') options: IHtmlRadioOption1[] = [];
}

[HtmlRadio1.template.html]

<span>  <!--  ngDefaultControl -->
    <div *ngFor="let opt of options">
        <input type="radio" [attr.id]="inputId" [attr.name]="inputId" [(ngModel)]="value" [value]="opt.value" checked="(value === opt.value)" /> {{ opt.label }}
    </div>
<span>

{{ value | json }}

1 个答案:

答案 0 :(得分:1)

您没有向name指令提供RadioControlValueAccessor属性,因此angular认为您的所有无线电控件属于名称为undefined的同一组,并通过调用正确尝试选择/取消选择RadioControlRegistry.select

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

要解决此问题,您需要打开 HtmlRadio1.template.html 文件并替换

[attr.name]="inputId"

[name]="inputId"