Угловой реактивный от. formarray. не удается найти элемент управления с помощью пути

Я хочу вывести форму, в которой одно поле представляет собой массив, и для каждого элемента массива мне нужно вывести мои входные данные.

Составная часть:

userData.contacts = [
{contact_type: "phone", value: "380666666666"},
{contact_type: "email", value: "ggg@gg.gg"},
{contact_type: "website", value: "www.good.co"}
];

this.contactInfoForm = new FormGroup ({
          contacts: this.fb.array (userData.contacts)
        });

HTML:

<form [formGroup] = "contactInfoForm" novalidate (ngSubmit) = "submit ('contactInfoForm')">
<div formArrayName = "contacts" * ngFor = "let contact of contactInfoForm.get ('contacts'). controls; let i = index;">
              <div formGroupName = "i">
                <label> {{contact.value.contact_type}} </ label>
                <input formControlName = "value">
              </ div>
            </ div>
</ form>

Если вывести в консоль форму то там объект с кучей данных.

  asyncValidator: null
controls:
contacts: FormArray
asyncValidator: null
controls: Array (3)
0: FormControl {validator: null, asyncValidator: null, _onCollectionChange: ƒ, pristine: true, touched: false, ...}
1: FormControl {validator: null, asyncValidator: null, _onCollectionChange: ƒ, pristine: true, touched: false, ...}
2: FormControl {validator: null, asyncValidator: null, _onCollectionChange: ƒ, pristine: true, touched: false, ...}
length: 3
__proto__: Array (0)
dirty: (...)
disabled: (...)
enabled: (...)
errors: null
invalid: (...)
length: (...)
parent: (...)
pending: (...)
pristine: true
root: (...)
status: DISABLED
statusChanges: EventEmitter {_isScalar: false, observers: Array (0), closed: false, isStopped: false, hasError: false, ...}
touched: false
untouched: (...)
updateOn: (...)
valid: (...)
validator: null
value: (3) [{...}, {...}, {...}]
valueChanges: EventEmitter {_isScalar: false, observers: Array (0), closed: false, isStopped: false, hasError: false, ...}
_onCollectionChange: ƒ ()
_onDisabledChange: []
_parent: FormGroup {validator: null, asyncValidator: null, _onCollectionChange: ƒ, pristine: true, touched: false, ...}
__proto__: AbstractControl
__proto__: Object
dirty: (...)
disabled: (...)
enabled: (...)
errors: null
invalid: (...)
parent: (...)
pending: (...)
pristine: true
root: (...)
status: DISABLED
statusChanges: EventEmitter {_isScalar: false, observers: Array (0), closed: false, isStopped: false, hasError: false, ...}
touched: false
untouched: (...)
updateOn: (...)
valid: (...)
validator: null
value: {contacts: Array (3)}
valueChanges: EventEmitter {_isScalar: false, observers: Array (0), closed: false, isStopped: false, hasError: false, ...}
_onCollectionChange: ƒ ()
_onDisabledChange: []
__proto__: AbstractControl

Я пытался получить информацию разными способами. Это не работает. Даже если тупо копипастить кусочки из примеров в инете. Те же проблемы. Те же ошибки.

Ошибка:

 Cannot find control with path: 'contacts -> 0 -> value'

Также пробовал:

<input [formControlName]="contact.value.value">

Получил ошибку:

contacts -> 0 -> 380666666666

ваш *ngFor должен находиться не в вашем элементе formArrayName=..., а в одном дочернем элементе ниже. Вы должны ngFor потомками formArray.

dee zg 10.09.2018 10:05

я пробовал раньше. тоже не вышло. но я попробую сейчас еще раз

Maxim 10.09.2018 10:13

не помогло. Ничего не изменилось.

Maxim 10.09.2018 10:25
1
3
3 006
2

Ответы 2

Вам необходимо предоставить массив элементов FormControl для ваших контактов вместо простого массива.

const formControlArray = [];
userData.contacts.forEach(contact => {
  formControlArray.push(new FormControl(contact.value));
})

this.contactInfoForm = new FormGroup ({
  contacts: this.fb.array(formControlArray)
});

Но я не уверен, что FormArray - лучший выбор для вашего варианта использования, поскольку элементы должны иметь разные имена. Вы также можете просто динамически добавлять элементы управления таким образом:

this.contactInfoForm = new FormGroup({});

userData.contacts.forEach(contact => {
  contactInfoForm.addControl(contact.contact_type, new FormControl(contact.value));
})

Я не хочу использовать карту или foreach. FormBuilder.array () - стандартная функция. я хочу использовать это) но спасибо.

Maxim 10.09.2018 11:16

Но вам все равно нужно будет обернуть свои контактные данные в FormControl. Конструктор FormArray поддерживает не только простые объекты.

Borys Kupar 10.09.2018 11:26

Составная часть:

 userData.contacts = [{
        contact_type: "phone",
        value: "380666666666"
    }, {
        contact_type: "email",
        value: "ggg@gg.gg"
    }, {
        contact_type: "website",
        value: "www.good.co"
    }];

    this.contactInfoForm = new FormGroup({
        contacts: this.fb.array([
            ...this.userData.contacts.map(({ contact_type, value }) => {
                return this.fb.group({
                    contact_type,
                    value
                });
            })
        ])
    });

HTML:

 <form [formGroup]="contactInfoForm" novalidate (submit)="submit('contactInfoForm')">
        <div formArrayName="contacts" *ngFor="let contact of contactInfoForm.get('contacts').controls; let i = index;">
            <div [formGroupName]="i" >
                <label>{{ contact.value.contact_type }}</label>
                <input formControlName="value">
            </div>
        </div>
    </form>

Работает отлично. но мне все еще не нравится использовать метод карты.

Отлично. Я не уверен, что вы можете избежать использования map или forEach. В любом случае вам нужно перебрать свои контакты и создать несколько элементов FormGroup.

Borys Kupar 13.09.2018 17:32

Другие вопросы по теме