Как обновить поле реактивной формы нажатием кнопки на другом компоненте?

#javascript #angular #typescript #angular-reactive-forms #angular9

#javascript #angular #typescript #angular-reactive-forms #angular9

Вопрос:

У меня есть приложение, в котором мое требование заключается в том, чтобы при нажатии кнопки (присутствующей в компоненте заголовка) поле формы в другом компоненте обновлялось. Но проблема в том, что значение устанавливается в переменной управления формой, но не отражается в пользовательском интерфейсе. Это пример кода, который я создал. При нажатии кнопки в журнале консоли вы можете увидеть, что форма имеет значение, но не отображается в пользовательском интерфейсе. Ниже я показываю свой код, что я сделал до сих пор :

Дочерний компонент

 // In TS
test = this.fb.group({
    sample: [""]
});

// In HTML
<form [formGroup]="test">
  <input placeholder="Sample" formControlName="sample" />
</form>
  

Компонент заголовка

 // In TS
import { ChildComponent } from "../child/child.component";

constructor(private child: ChildComponent) {}

set() {
  this.child.test.patchValue({
    sample: "fetched value"
  });
  console.log(this.child.test.value);
}

// In HTML
<button (click)="set()">ABC</button>
  

app.module.ts

 import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';

import { AppComponent } from './app.component';
import { HeaderComponent } from './header/header.component';
import { ChildComponent } from './child/child.component';
import { AppRouterModule } from './router/router.module';

@NgModule({
  imports:      [ BrowserModule, FormsModule, AppRouterModule, ReactiveFormsModule ],
  declarations: [ AppComponent, HeaderComponent, ChildComponent ],
  providers: [ ChildComponent ], // Specified child component to access through different component
  bootstrap:    [ AppComponent ]
})
export class AppModule { }
  

app.component.html

 <app-header></app-header>
<router-outlet></router-outlet>
  

Итак, это мой код. Кто-нибудь может сказать мне, в чем проблема?

Ответ №1:

Это не то, как взаимодействие компонентов работает в Angular. Чтобы обмениваться данными между компонентами, вы можете использовать либо EventEmitter для связанных компонентов, либо одноэлементный сервис для несвязанных компонентов.

Вот иллюстрация с использованием одноэлементного сервиса

share.service.ts

 import { Injectable } from "@angular/core";

import { ReplaySubject } from "rxjs";

@Injectable()
export class ShareService {
  public headerClickSrc = new ReplaySubject<any>(1);
  public headerClick$ = this.headerClickSrc.asObservable();

  constructor() {}
}
  

header.component.ts

 import { Component } from "@angular/core";
import { ShareService } from "../share.service";

@Component({
  selector: "app-header",
  templateUrl: "./header.component.html"
})
export class HeaderComponent {
  constructor(private share: ShareService) {}

  set() {
    this.share.headerClickSrc.next("fetched value");
  }
}
  

child.component.ts

 export class ChildComponent implements OnInit, OnDestroy {
  closed$ = new Subject<any>();
  constructor(private fb: FormBuilder, private share: ShareService) {}

  test = this.fb.group({
    sample: [""]
  });

  ngOnInit() {
    this.share.headerClick$.pipe(
      takeUntil(this.closed$)
    ).subscribe({
      next: value => {
        this.test.patchValue({
          sample: value
        });
        console.log(this.test.value);
      }
    });
  }

  ngOnDestroy() {
    this.closed$.next(); // <-- close open subscriptions
  }
}
  

Я изменил ваш Stackblitz

Комментарии:

1. Это выдает ошибку 1. Если set() метод запускается один раз из header.component.ts ngOnInit дочернего элемента, он работает нормально. Но после этого, если я перейду к любому другому компоненту и вернусь сюда снова value subscribe , значение внутри ngOnInit остается верным. Есть ли способ это исправить? ngOnDestroy Используется по-прежнему без изменений