Angular FormGroup не определена внутри локального метода

У меня есть 2 компонента параллельно, и я пытаюсь ввести 1 компонент в другой. Ниже представлены мои файлы компонентов:

RegisterComponent.html

<mat-tab #tab label="Contact Details">
  <ng-template matTabContent>
    <app-contact-details></app-contact-details>
  </ng-template>
</mat-tab>

<button type="button" (click)="changeTabOrStepViaContinue()" class="">Continue</button>

RegisterComponent.ts

changeTabOrStepViaContinue() {
    if (this.tabGroup._tabs.first.isActive) {
      this.tabGroup.selectedIndex += 1;
    } else if (this.tabGroup._tabs.last.isActive /* &&  this.isContactFormValid() */) {
        this.contactDetails.validateContactDetails(); //throws Error
      console.log("Contact details form: ", this.contactDetailsForm);
    } else if (this.isPersonalDetailsFormValid()) {
        this.tabGroup.selectedIndex += 1;
    }
  }

ContactDetailsComponent.ts (внедряемый компонент)

ngOnInit() {
    console.log("Contct det ngOnInit fired......")
    this.contactDetailsForm = this.formBuilder.group({
      primaryMobile: ['', [Validators.required]],
      primaryMobileOwner: ['', [Validators.required]],
      primaryEmail: ['', [Validators.required]],
      primaryEmailOwner: ['', [Validators.required]],
      landLine: [''],
      country: ['', [Validators.required]],
      pinCode: ['', [Validators.required]],
      flat: ['', [Validators.required]],
      street: [''],
      postOffice: ['', [Validators.required]],
      locality: ['', [Validators.required]],
      district: ['', [Validators.required]],
      state: ['', [Validators.required]]
    })
}

validateContactDetails(): boolean {
    console.log(this.contactDetailsForm);
    Object.keys(this.contactDetailsForm.controls).forEach(elt => {
      this.contactDetailsForm.get(elt).markAsTouched();
    })
    if (this.contactDetailsForm.valid) {
      this.contactDetails.emit(this.contactDetailsForm);
      return true;
    }
    return false;
  }

Я сделал ContactDetailsComponent сервисом, включив @Injectable({providedIn:'root'}), а также внедрил его в конструктор RegisterComponent как constructor(private contactDetails:ContactDetailsComponent).

Когда я выбираю конкретную вкладку mat, запускается ngOnInit для ContactDetailsComponent (он загружается лениво, так как внутри ng-шаблона), но при нажатии кнопки продолжения отображается ошибка TypeError: Cannot read property 'controls' of undefined.

Почему FormGroup undefined находится внутри локальной функции?

Обновить

Я утешил this контекст для ContactDetailsComponent и обнаружил, что у него нет свойства contactDetailsForm. Затем я изменил объявление переменной с contactDetailsForm:FormGroup на contactDetailsForm:FormGroup=new FormGroup({}), а затем он был зарегистрирован на this, но проверки, помещенные в FormControls внутри ngOnInit, больше не работают. Я также добавил к компоненту еще одну FormGroup, и происходит то же самое. Похоже, что this регистрирует только инициализированные свойства, хотя я не уверен, почему это происходит.


person Samarth Saxena    schedule 06.06.2020    source источник


Ответы (1)


Вы пытаетесь вызвать дочерний метод от родителя?

Судя по тому, что я вижу, вам не нужно ничего вводить, если только это не нужно где-то еще, о чем вы нам не говорите. Вы можете просто добавить идентификатор в свои контактные данные приложения и использовать ViewChild для получения ссылки. Есть несколько способов использовать ViewChild, это может быть не лучшим для вас, но это всего лишь пример.

<app-contact-details #contactDetail></app-contact-details>

@ViewChild('contactDetail') contactDetail: ContactDetailsComponent; // In the parent ts file

Затем, если вы хотите увидеть, был ли он инициализирован, проверьте ngAfterViewInit родительского элемента, где у вас должен быть доступ к дочерней функции (вам может потребоваться привести contactDetail в качестве типа вашего компонента или вы используете другую инициализацию ViewChild), если они public, потому что на этом этапе должен был быть вызван OnInit детей.

  ngAfterViewInit() {
     // you can try to print your form
  } 

Причина, по которой ваша форма не инициализирована, заключается в том, что вы не ссылаетесь на правильный экземпляр, если только компонент не является синглтоном. Используя проекцию контента (как вы это делаете), компонент будет инициализирован, как только angular начнет его отображать (здесь в дочернем элементе вызывается OnInit).

person ukn    schedule 07.06.2020
comment
Спасибо за ответ. На самом деле, точки компонентов действительно связаны отношениями родитель-потомок. они являются родственными компонентами. И компонент contactDetails должен использоваться как минимум в 5 разных местах, поэтому я сделал его как услугу. - person Samarth Saxena; 07.06.2020
comment
Это не брат или сестра, если вы вводите его с помощью проекции контента. Использование компонента в 5 разных местах не требует обслуживания, в этом смысл использования компонентов! - person ukn; 07.06.2020
comment
Я также попытался использовать предоставленный вами ответ, и он выдает ошибку cannot read property 'validateContactDetails' of undefined - person Samarth Saxena; 07.06.2020
comment
Откуда вы это назвали? - person ukn; 07.06.2020
comment
изнутри RegisterComponent. ts файл - person Samarth Saxena; 07.06.2020
comment
Да, но какой крючок жизненного цикла - person ukn; 07.06.2020
comment
на самом деле я вызвал это внутри функции, вызываемой нажатием кнопки. - person Samarth Saxena; 07.06.2020
comment
Если он не определен, это потому, что viewchild не инициализируется правильно, посмотрите угловую документацию, так как есть несколько способов сделать это. - person ukn; 07.06.2020
comment
Я изменил тип определения viewchild с ElementRef на ContactDetailsComponent, и это сработало. Обновите свой ответ, чтобы я мог его принять. Я потратил колоссальные 2 дня, пытаясь понять, почему это не работает. Спасибо огромное :-) - person Samarth Saxena; 07.06.2020
comment
Если вы присмотритесь, я сказал, что вам, возможно, потребуется отлить его! - person ukn; 07.06.2020
comment
Хотя я до сих пор не понимаю, почему контекст теряется в случае службы, поскольку, когда я изначально разместил вопрос, ContactDetailsComponent был службой - person Samarth Saxena; 07.06.2020
comment
Это потому, что экземпляр, который вы вводите, не тот, который отображается - person ukn; 07.06.2020
comment
@SamarthSaxena есть причина, по которой вы не приняли ответ? - person ukn; 10.06.2020