简体   繁体   English

RadioButtonGroup-formControlName不适用于反应式表单

[英]RadioButtonGroup-formControlName not working with reactive forms

I want to a create a RadioComponent which populates the input and Label. 我想创建一个RadioComponent来填充输入和Label。

I want this component to work with ngModel and reactive forms. 我希望该组件可以使用ngModel和反应形式。

So i created a RadioGroup by implementing ControlValueAccessor, and RadioButton Component which populates Input and Label. 因此,我通过实现ControlValueAccessor和填充Input和Label的RadioButton Component创建了RadioGroup。

I am calling these component from a parent component where I defined FormGroup but reactive form is not working with this approach. 我从定义FormGroup的父组件中调用这些组件,但反应形式无法使用此方法。

Can someone please suggest where I am going wrong. 有人可以建议我要去哪里错了。

https://stackblitz.com/edit/angular-mipzzw https://stackblitz.com/edit/angular-mipzzw

RadioGroupComponent RadioGroupComponent

import { Component, Input, forwardRef, ContentChildren, QueryList } from '@angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor, FormGroup } from '@angular/forms';
import { RadioButtonComponent } from '../radio-button/radio-button.component';

@Component({
  selector: 'radio-group',
  templateUrl: './radio-group.component.html',
  styleUrls: ['./radio-group.component.css'],
providers: [
        {
            provide: NG_VALUE_ACCESSOR,
            useExisting: forwardRef(() => RadioGroupComponent),
            multi: true
        }
    ],
})
export class RadioGroupComponent implements ControlValueAccessor {

  constructor() { }

 private _value: any = null;

    @ContentChildren(forwardRef(() => RadioButtonComponent), { descendants: true })
    radios: QueryList<RadioButtonComponent>;

    _onChange = (value: any) => {
        console.log('onChange=', value);
    }
    _onTouched = () => { };

    writeValue(value: any): void {
        console.log('writeValue=', value);
        this._onChange(value);
    }

    registerOnChange(fn: (_: any) => {}): void {
        this._onChange = fn;
    }

    registerOnTouched(fn: () => {}): void {
        this._onTouched = fn;
    }

    get value(): any {
        console.log('get value', this._value);
        return this._value;
    }

    set value(val) {  // this value is updated by programmatic changes
        if (val !== undefined && this._value !== val) {
            this._value = val;
            this._onChange(val);
            this._onTouched();
        }
    }
}

RadioComponent 无线电组件

import { Component, Input, Output, EventEmitter, forwardRef } from '@angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor, FormGroup } from '@angular/forms';

@Component({
    selector: 'radio-button',
    template: `
        <input type="radio"
            (change)="changeValue(value)"
            class="input-control"
            [id]="inputId"
            [(ngModel)]="selectedOption"
            [value]="value"
            [formControlName]="inputName"/>

        <label
            for="{{ inputId }}">
            <span>{{ label | translate }}</span>
        </label>
    `,        
    styleUrls: ['./radio.less']
})

export class RadioComponent {
    @Input() selectedOption: string;
    @Input() inputId: string;
    @Input() value: string;
    @Input() label: string;
    @Input() inputName: string;

    @Output() selectedOptionChange: EventEmitter<any> = new EventEmitter<any>();

    changeValue(value: any) {
        this.selectedOptionChange.emit(value);
    }                                            
}

Demo Component 演示组件

import { Component, Input, OnInit } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';

@Component({
    selector: 'app-radio',
    template: `

            <div  [formGroup]="exampleForm">
                <radio-button *ngFor="let option of options"
                    [inputId] = "option.value"
                    [label]="option.display"
                    [value]="option.value"
                    (selectedOptionChange) = "selectedOptionChange($event)"
                    formInputName= "gender"
                    [selectedOption]="options[0].value">
                </radio-button>
            </div>

            </section>
            <h3>Selected value = {{selectedOption}} </h3>
            `,
})

export class DemoComponent implements OnInit {
    constructor(private fb: FormBuilder) { }

    exampleForm = this.fb.group({
        gender: ['', []],
    });

    selectedOption: string;

    options: Array<{ value: string, display: string }> = [
        { value: 'Male', display: 'Male' },
        { value: 'Female', display: 'Female' }
    ];

    ngOnInit() {
        this.selectedOptionChange(this.options[0].value);
    }

    selectedOptionChange(value: any): void {
        this.selectedOption = value;
    }
}

You probably also need to ask for your formGroup as an Input 您可能还需要将formGroup作为输入

 @Input() group: FormGroup; 

and also you need an element that acts as container where you add the directive 并且您还需要一个充当容器的元素,您可以在其中添加指令

[formGroup]

check the edit of your code I made 检查我对您的代码所做的编辑

    import { Component, Input, Output, EventEmitter, forwardRef } from '@angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor, FormGroup } from '@angular/forms';


@Component({
  selector: 'radio-button',
  //You will also need a DOM element to act as a container of your formControl
  template: `
    <div [formGroup]="group">
        <input type="radio"
            (change)="changeValue(value)"
            class="input-control"
            [id]="inputId"
            [(ngModel)]="selectedOption"
            [value]="value"
            [formControlName]="inputName"/>

        <label
            for="{{ inputId }}">
            <span>{{ label | translate }}</span>
        </label>
        </div>
    `,
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => RadioComponent),
      multi: true
    }
  ],
  styleUrls: ['./radio.less']
})

export class RadioComponent implements ControlValueAccessor {
  @Input() selectedOption: string;
  @Input() inputId: string;
  @Input() value: string;
  @Input() label: string;
  @Input() inputName: string;
  @Input() group: FormGroup; //You also need to ask for the formgroup 

  @Output() selectedOptionChange: EventEmitter<any> = new EventEmitter<any>();

  changeValue(value: any) {
    this.selectedOptionChange.emit(value);
  }

  _onChange = (_: any) => { };
  _onTouched = () => { };


  writeValue(value: any): void {
    console.log('writeValue=', value);
    this._onChange(value);
  }


  registerOnChange(fn: (_: any) => {}): void {
    this._onChange = fn;
  }


  registerOnTouched(fn: () => {}): void {
    this._onTouched = fn;
  }
}

you could also post a working example so we could better help you. 您还可以发布一个有效的示例,以便我们更好地为您提供帮助。 Maybe upload it to https://stackblitz.com 也许将其上传到https://stackblitz.com


EDIT 编辑

For completeness sake I´ve also added the part of your demo component 为了完整起见,我还添加了演示组件的一部分

import { Component, Input, OnInit } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';

@Component({
    selector: 'app-radio',
    template: `

            <div  [formGroup]="exampleForm">
                <radio-button *ngFor="let option of options"
                    [inputId] = "option.value"
                    [label]="option.display"
                    [value]="option.value"
                    (selectedOptionChange) = "selectedOptionChange($event)"
                    formInputName= "gender"
                    [selectedOption]="options[0].value"
                    [group]="exampleForm"
                    >
                </radio-button>
            </div>

            </section>
            <h3>Selected value = {{selectedOption}} </h3>
            `,
})

export class DemoComponent implements OnInit {
    constructor(private fb: FormBuilder) { }

    exampleForm = this.fb.group({
        gender: ['', []],
    });

    selectedOption: string;

    options: Array<{ value: string, display: string }> = [
        { value: 'Male', display: 'Male' },
        { value: 'Female', display: 'Female' }
    ];

    ngOnInit() {
        this.selectedOptionChange(this.options[0].value);
    }

    selectedOptionChange(value: any): void {
        this.selectedOption = value;
    }
}

EDIT: proof of concept 编辑:概念证明

You can check a proof of concept here . 您可以在此处检查概念证明。 It is a barebones version of what you are doing. 这是您所做工作的准系统版本。 It only has 3 components. 它只有3个组件。 The app-component, and two more similar to what you are doing. 应用程序组件,另外两个与您正在执行的操作类似。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Angular 反应式 forms:将值绑定到 formcontrolname - Angular reactive forms: bind value to formcontrolname Angular 2 反应式表单 - 从 formControlName 管道传递一个值 - Angular 2 reactive forms - piping a value from a formControlName formControlName 中的日期未使用反应形式取值 - Date in formControlName not taking the value using reactive forms 如何获取值在 Angular 中更改的字段的 FormControlName 反应 forms - How to get FormControlName of the field which value changed in Angular reactive forms 在angular的反应式forms中,为什么formControlName中传递的参数是作为字符串传递的? - In reactive forms of angular, why the parameter passed in formControlName is passed as a string? Angular 反应性 Forms map 仅是 ZA8CFDE6331BD59EB2AC96F8911C4B6666 的一部分 - Angular Reactive Forms map only part of object to formControlName Angular 反应 forms:使用单个 formControlName 同步多个输入 - Angular reactive forms: sync multiple inputs with a single formControlName 连接中 <li> 带有formControlName的标签,使用Reactive Forms的FormBuilder - connecting <li> tag with formControlName, FormBuilder using Reactive Forms 如何以反应形式绑定,即 angular 中的 formcontrolname 和 ngmodel - How to bind in reactive forms which is the formcontrolname and ngmodel in angular 如何从子组件将“formControlName”添加到角度反应形式“formGroup”? - How to add "formControlName" to angular reactive forms "formGroup" from child components?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM