formGroup ожидает экземпляр FormGroup: умный и тупой компонент

У меня есть реактивная форма, которая перемещается из смарт-компонента в немой компонент, и я знаю, что эта ошибка означает, что форма по какой-то причине не привязана, я просто не могу понять, почему...

Я посмотрел на это с авэри, и не могу найти проблему. Я перезагрузил свой код и безуспешно повторно обслуживал его. Я основывал это точно на рабочей версии, которая у меня уже есть, и не могу найти никаких отличий. Я прошел все шаги, я создал var, создал formGroup onInit, добавил элемент управления формой, передал его дочернему компоненту, использовал @Input и создал привязку формы и имя formControl в html.

Это потому, что он рендерится до того, как форма может быть привязана? Как это исправить?

полная ошибка:

ERROR Error: formGroup expects a FormGroup instance. Please pass one in.

указывая на первую строку моей формы в моем немом компоненте. а также

TypeError: Cannot read property 'get' of undefined

когда я пытаюсь прочитать состояние формы в html

view.ts

import { Observable } from 'rxjs/Observable';
import { Dns } from './../models/network.models';
import { FormGroup, FormControl, Validators, FormBuilder } from '@angular/forms';
import { NetworkValidator } from './../networkValidator.service';
import { NetworkService } from './../network.service';
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-dns-view',
  templateUrl: './dns-view.component.html',
  styleUrls: ['./dns-view.component.css']
})
export class DnsViewComponent implements OnInit {

    dnsForm: FormGroup;
    dnsServers$: Observable<string[]>;

    constructor(private formBuilder: FormBuilder,
                private networkService: NetworkService,
                private networkValidator: NetworkValidator) {}

    ngOnInit() {

        this.dnsForm = this.formBuilder.group({
            ip: [null, Validators.required, this.networkValidator.validateNetwork('ip')]
        });

    }

вид.html

<app-dns
    [dnsServers$]="dnsServers$"
    [dnsForm]="dnsForm"
    (addIp)="addIp($event)"
    (deleteIp)="deleteIp($event)"
>
</app-dns>

тупой.тс

import { Dns } from './../models/network.models';
import { FormGroup } from '@angular/forms';
import { Component, Input, Output, EventEmitter } from '@angular/core';

@Component({
    selector: 'app-dns',
    templateUrl: './dns.component.html',
    styleUrls: ['./dns.component.css']
})
export class DnsComponent {
    // initialize form vars
    @Input() dnsServers$;
    @Input() dnsForm: FormGroup;
    // @Input() editForm: FormGroup;

    @Output() deleteIp: EventEmitter<Dns> = new EventEmitter<Dns>();
    @Output() addIp: EventEmitter<FormGroup> = new EventEmitter<FormGroup>();


}

немой.html

<div class="title row">
    <div class="col">
        DNS
    </div>
</div>
<div>
    <div class="row">
        <div class="col"></div>
        <div class="server-list col-7">
            <div
                class="server row"
                *ngFor="let server of dnsServers$ | async; let index = index"
            >
                <div class="read row"
                    appListHighlight
                    [index]="index"
                >
                    <div class="col"></div>
                    <div class="col-3">
                        <label for="servers">
                            {{ server }}
                        </label>
                    </div>
                    <div class="col"></div>
                    <div class="col">
                        <div class="x">
                            <i
                                class="fa fa-times-circle"
                                aria-hidden="true"
                                (click)="deleteIp.emit(server)"
                            ></i>
                        </div>
                    </div>
                    <div class="col"></div>
                </div>
            </div>
        </div>
        <div class="col"></div>
    </div>
    <form
        autocomplete="off"
        [formGroup]="dnsForm"
        (ngSubmit)="addIp.emit(dnsForm)"
    >
        <div class="add-server row">
            <div class="col"></div>
            <div class="col-2">
                <label for="add-server">
                    <button class="btn btn-primary" type="submit">
                        Add Server IP
                    </button>
                </label>
            </div>
            <div class="col-5">
                <input
                    type="text"
                    class="form-control"
                    formControlName="ip"
                    placeholder="8.8.8.8"
                >
                <div
                    class="invalid-box alert alert-danger"
                    *ngIf="!dnsForm.get('ip').valid && dnsForm.get('ip').dirty"
                >
                    Invalid IP address
                </div>
            </div>
            <div class="col"></div>
        </div>
    </form>
</div>

person FussinHussin    schedule 18.09.2017    source источник
comment
Каково точное сообщение об ошибке? Также вы пробовали хук ngAfterViewInit()?   -  person Alex Beugnet    schedule 18.09.2017
comment
Я бы поставил на ошибку при создании формы, вызвавшую указанную вами ошибку. this.networkValidator.validateNetwork('ip') возвращает функцию? Если нет, то это ваша проблема.   -  person Grégory Elhaimer    schedule 18.09.2017
comment
привет @GrégoryElhaimer, да, он возвращает функцию и уже работает над другими компонентами.   -  person FussinHussin    schedule 18.09.2017
comment
@AlexBeugnet полная ошибка: ERROR Ошибка: formGroup ожидает экземпляр FormGroup. Пожалуйста, передайте один.   -  person FussinHussin    schedule 18.09.2017
comment
@AlexBeugnet, могу ли я поместить свой код конструктора форм в этот хук в моем компоненте представления? или в моем тупом компоненте? Я не очень понимаю это, так как у меня есть компонент, настроенный точно так же, без использования ngAfterViewInit(), и он отлично работает   -  person FussinHussin    schedule 18.09.2017
comment
может быть, что в первом проходе, прежде чем вы инициализируете свою форму, вы вводите значение своей формы в тупой компонент и получаете эту ошибку. проверьте хук ngOnChanges() в вашем немом компоненте, если вы получите какое-либо значение для своей формы   -  person JayDeeEss    schedule 18.09.2017
comment
Групповой метод FormBuilder ожидает массив функций для валидаторов. Попробуйте удалить валидатор и проверьте, работает ли он.   -  person Grégory Elhaimer    schedule 18.09.2017
comment
@GrégoryElhaimer хорошо, я удалил это, все равно ничего   -  person FussinHussin    schedule 18.09.2017
comment
@JayDeeEss ничего не показывает   -  person FussinHussin    schedule 18.09.2017


Ответы (2)


Я думаю, это связано с отсутствием допустимого объекта formGroup для передачи вашему тупому компоненту в качестве входного свойства, в то время как интеллектуальный компонент «построен». Попробуйте создать экземпляр formGroup в constructor вашего смарт-компонента (в настоящее время вы делаете это внутри хука OnInit).

view.ts

export class DnsViewComponent {

 dnsForm: FormGroup;
 dnsServers$: Observable<string[]>;

 constructor(private formBuilder: FormBuilder,
            private networkService: NetworkService,
            private networkValidator: NetworkValidator) {
  this.dnsForm = formBuilder.group({
        ip: [null, [Validators.required, networkValidator.validateNetwork('ip')]]
    }); // 'networkValidator' referenced without 'this.' as it is a constructor argument
 }
// no ngOnInit hook implementation
}

Посмотрите, решит ли это вашу проблему.

person amal    schedule 18.09.2017
comment
Думал так же, не должно быть никаких других причин, чтобы это не сработало. - person Alex Beugnet; 18.09.2017
comment
@amal Я пробовал это, все еще не работает, та же ошибка: / - person FussinHussin; 18.09.2017
comment
Я обновил свой ответ. Посмотрите, поможет ли это изменение: ip: [null, [Validators.required, networkValidator.validateNetwork('ip')]] дополнительные [] вокруг списка валидаторов - person amal; 18.09.2017
comment
@amal, который просто помещает синхронизирующий и асинхронный валидатор в синхронизирующую часть массива валидаторов, это не работает - person FussinHussin; 18.09.2017
comment
извините, не знал, что ваш второй валидатор был «асинхронным» - person amal; 18.09.2017

Проблема заключалась в том, что я рендерил свой тупой компонент в своем маршрутизаторе, а не умный компонент.

глупая ошибка, заняло у меня несколько часов. Спасибо за всю помощь, ребята.

person FussinHussin    schedule 18.09.2017