FormGroup обновляет значение FormControl для радиостанций сразу после их добавления - PullRequest
0 голосов
/ 16 ноября 2018

Проблема

При добавлении радиосигналов к FormGroup значение для FormControl обновляется немедленно.Кроме того, изменение выбранной радиокнопки не приводит к обновлению значения FormControl.

Код

Мой код - это система динамических форм, использующая службу (FormService) для поддержки одиночного кода.FormGroup с функциями для добавления и удаления входных данных по мере необходимости.

Все мои входные данные расширяют базовый входной класс с именем InputBaseComponent, который импортирует FormService, создает для себя элемент управления формой и добавляет его в FormGroup через сервис.InputBaseComponent также содержит все общие функциональные возможности, которые одинаковы для всех входных данных.

FormService

Сервис форм - это довольно универсальный сервис, который регулирует FormGroup с помощью getter/ Сеттер функции.Эта услуга импортируется InputBaseComponent, который расширяется каждым отдельным компонентом ввода.

import { Injectable } from '@angular/core';
import { FormGroup } from '@angular/forms';

@Injectable()
export class FormService {

    // An arry of all the inputs in the form
    inputs: any[] = [];

    // The form group for this instance of the form service singleton
    formGroup: FormGroup = new FormGroup({});

    // Adds an input to the array of inputs in the form
    addInput( input: any ){

        // Push the input to the array if it's not already in the inputs array
        if ( this.inputs.indexOf(input) === -1 ) this.inputs.push(input);

        // Push the input's form control to the form group if it doesn't already exist
        if ( !this.formGroup.contains(input.name) ) this.formGroup.addControl(input.name, input.formControl);
    }

    // Removes an input from the array of inputs in the form
    removeInput( input: any ){

        // Remove the input from the array if it exists
        this.inputs.filter( arrayInput => arrayInput !== input);

        // Remove the control from the form group
        if ( this.formGroup.contains(input.name) ) this.formGroup.removeControl(input.name);
    }
}

BaseInputComponent

Это базовый компонент ввода, который расширяют все действительные компоненты ввода.Это сделано для того, чтобы сохранить все общие функциональные возможности в одном месте, чтобы не повторять код для каждого ввода.Для простоты я обрезал все входные данные в конце, но, поверьте мне, они есть.

// ---------- Imports ---------- //

    import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
    import { FormControl, Validators, ValidatorFn } from "@angular/forms";

    /// ---------- Dependencies ---------- ///

        import { FormService } from "../form.service";

// ---------- Components ------- //
    @Component({
        selector: 'input-base-component-do-not-use-directly',
        template: ``
    })
    export class InputBaseComponent implements OnInit {

        /// ---------- Constructor ---------- ///

            constructor ( public formService: FormService ){};

        /// ---------- Properties ----------- ///

            // A reference to this form input's form control
            formControl: any;

        /// ---------- Methods -------------- ///

            // On init set up the form control with the proper validators
            ngOnInit() {

                // Setup the form control with the proper validators
                this.setupFormControl( this.getValidators() );
            }

            // Creates an array of all of the validator functions that should apply to the input and returns it
            getValidators(): ValidatorFn[] {

                // Create the validators array
                let validators: any[] = [];

                // Set the max length validator
                if (this.maxLength) validators.push(Validators.maxLength(this.maxLength));

                // Set the min length validator
                if ( this.minLength ) validators.push(Validators.minLength(this.minLength));

                // Set the required validator
                if ( this.required ) validators.push(Validators.required);

                // Include any custom validators
                if ( this.customValidators && this.customValidators.length ) validators = validators.concat(this.customValidators);

                // Return the array of validator functions
                return validators;
            }

            // Sets up the form control and adds it to the form service
            setupFormControl( validators: ValidatorFn[] ): void {

                // Create the form control for this input
                if (this.formService.formGroup.contains(this.name)) {
                    this.formControl = this.formService.formGroup.get(this.name)
                } else {
                    this.formControl = this.getNewFormControl( validators );
                    this.formService.addInput(this);
                }

                // Update the parent component whenever this input's value is changed
                this.formControl.valueChanges.subscribe( newValue => this.valueChange.emit(newValue));

                // Add the input to the form group
                this.formService.addInput(this);
            }

            // Takes an array of validator functions and returns a new form control with all of the proper setup for this input
            getNewFormControl( validators: ValidatorFn[] ): FormControl {

                // Return a new form control for this form
                return new FormControl( this.value || null, { validators: validators, updateOn: this.validateOn } );
            }
    }

Код интереса

Если вы посмотрите на следующие строки setupFormControl функция, которую вы можете видеть, что мы проверяем FormGroup, чтобы увидеть, существует ли уже FormControl с именем, заданным для входа, как в случае с переключателями и флажками.Если он уже существует, он использует этот существующий FormControl в качестве элемента управления формы для ввода.Это было сделано, чтобы имитировать правильную разметку для использования переключателей и флажков с реактивными формами, где-в каждом переключателе или флажке в группе используется один и тот же элемент управления формой.

// Create the form control for this input
if (this.formService.formGroup.contains(this.name)) {
    this.formControl = this.formService.formGroup.get(this.name)
} else {
    this.formControl = this.getNewFormControl( validators );
    this.formService.addInput(this);
}

Разметка, реализующая этот код, имеет видследует:

<!-- input -->
<input 
    #input 
    [formControl]="formControl" 
    [type]="type" 
    [name]="name" 
    [id]="idStr" 
    [value]="value" 
    tabindex="-1" 
/>

Возможное решение

Как указывалось ранее, с этой настройкой, как только элемент управления формой добавляется (или повторно используется на тех, кто находится после первого радио / флажка),значение экземпляра FormControl обновляется до последнего добавленного радио или флажка.Кроме того, каждый раз, когда изменяется выбранная радиостанция или флажок (и), значение FormControl не обновляется.

Требуемая функциональность

Желаемая функциональность здесь заключается в том, что FormControlсвойство value экземпляра будет оставаться как null, пока пользователь не выберет радио или флажок.Кроме того, при изменении выбранного радио или флажка (ов) значение FormControl должно обновиться.

1 Ответ

0 голосов
/ 14 декабря 2018

Итак, здесь есть два ответа: один для значения, а другой для значения, которое не обновляется.

Почему применяется значение

Если вы посмотрите на функцию getNewFormControl, у вас есть эта строка кода:

// Return a new form control for this form
return new FormControl( this.value || null, { validators: validators, updateOn: this.validateOn } );

Эту строку необходимо было обновить, чтобы учесть отсутствие установки значения для флажков и переключателей, поэтому простая проверка с использованием троичной переменной устраняет проблему:

// Return a new form control for this form
return new FormControl( this.type !== "radio" && this.type !== "checkbox" ? this.value || null : null, { validators: validators, updateOn: this.validateOn } );

Почему значение не обновлялось

В Angular 2+ существует известная ошибка, касающаяся динамических типов ввода для радио и флажка. Для этих типов ввода нельзя применять динамический тип к входу.

Этот код будет работать правильно:

<!-- input -->
<input 
    #input 
    [formControl]="formControl" 
    type="radio" 
    [name]="name"
    [value]="value"
/>

Этот код не будет работать вообще:

<!-- input -->
<input 
    #input 
    [formControl]="formControl" 
    [type]="myInputType" 
    [name]="name"
    [value]="value"
/>

К сожалению, это означает использование ngIf и двух отдельных входов, которые затем необходимо обновлять отдельно. Это известная ошибка начиная с Angular 2 RC.6, было бы неплохо, если бы они ее исправили.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...