Почему мой образец Stackblitz не работал?
Ответ о том, почему мой образец Stackblitz не работает должным образом, находится в исходном коде RadioControlRegistry (packages / forms / src /). directives / radio_control_value_accessor.ts).
select(accessor: RadioControlValueAccessor) {
this._accessors.forEach((c) => {
if (this._isSameGroup(c, accessor) && c[1] !== accessor) {
c[1].fireUncheck(accessor.value);
}
});
}
private _isSameGroup(
controlPair: [NgControl, RadioControlValueAccessor],
accessor: RadioControlValueAccessor): boolean {
if (!controlPair[0].control) return false;
return controlPair[0]._parent === accessor._control._parent &&
controlPair[1].name === accessor.name;
}
Когда вы нажимаете на неконтролируемый элемент управления радио, вызывается эта функция выбора. Он будет вызывать fireUncheck для других радиоуправлений с таким же свойством имени И с тем же родителем.
Эта последняя часть - проблема. Каждый пользовательский элемент управления радио имеет своего родителя. Родитель здесь относится к экземпляру FormGroupDirective. Каждый пользовательский элемент управления радио обернут в div, который получает новый экземпляр FormGroupDirective. FireUncheck никогда не вызывается.
Решение:
Если бы я как-то мог сделать родителей равными в этом сценарии, это сработало бы.
Я обнаружил, что могу использовать директиву formControl вместо директивы formControlName в радиокомпоненте.
Я создал модифицированную версию образца Stackblitz . Я заменил директивы formGroup и formControlName на директиву formControl. Работает как брелок.
Вот модифицированный код:
Пользовательский компонент радио html
<div>
<label [for]="id">
<input [id]="id" type="radio" [value]="value" [formControl]="ctrl">{{label}}
</label>
</div>
Пользовательское радио машинописный текст
import { Component, Input } from "@angular/core";
import { FormControl } from "@angular/forms";
@Component({
selector: 'app-radio',
templateUrl: './radio.component.html',
styleUrls: ['./radio.component.css']
})
export class RadioComponent {
@Input() ctrl: FormControl;
@Input() label: string;
@Input() value: string;
@Input() id: string;
}
HTML, где используется пользовательский радиокомпонент
<form [formGroup]="frm">
<app-radio id="rc1" label="Yes" value="Yes" [ctrl]="frm.get('question')" ></app-radio>
<app-radio id="rc2" label="No" value="No" [ctrl]="frm.get('question')"></app-radio>
</form>
<hr>
<h3>Form Data</h3>
<pre>{{frm.value | json}}
машинописный текст для html с использованием пользовательского радиокомпонент
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
frm: FormGroup;
constructor(private fb: FormBuilder){}
ngOnInit() {
this.frm = this.fb.group({
question: ['Yes', Validators.required]
});
}
}