RadioButtonGroup-formControlName必须与父formGroup指令一起使用

时间:2019-07-16 22:04:48

标签: angular angular-reactive-forms angular8

我创建了一个RadioComponent,它创建了一个输入和标签。

我从定义FormGroup的另一个组件中调用此组件,但是仍然出现上述错误。

有人可以建议我要去哪里了吗

正如我在示例中看到的那样,在我的示例中,必须在DemoComponent上直接在父控件上声明FormGroup。

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>
    `,
    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;

    @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;
    }
}

演示组件

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;
    }
}

1 个答案:

答案 0 :(得分:0)

您可能还需要将formGroup作为输入

 @Input() group: FormGroup; 

,还需要一个充当容器的元素,在其中添加指令

[formGroup]

检查您对我的代码所做的编辑

    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;
  }
}

您还可以发布一个有效的示例,以便我们更好地为您提供帮助。也许将其上传到https://stackblitz.com


编辑

出于完整性考虑,我还添加了演示组件的一部分

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;
    }
}

编辑:概念证明

您可以检查概念证明here。这是您所做工作的准系统版本。它只有3个组件。应用程序组件,另外两个与您正在执行的操作相似。