【问题标题】:How to update a reactive form field by button click on different component?如何通过单击不同组件的按钮来更新反应式表单字段?
【发布时间】:2021-02-13 15:02:30
【问题描述】:

我有一个应用程序,我的要求是单击按钮(出现在标题组件中),另一个组件中的表单字段将得到更新。但问题是在表单控制变量中设置了值,但没有反映在 UI 中。这是我创建的sample code。您可以在控制台日志中单击按钮时看到表单具有值但未在 UI 中呈现。下面我展示了我到目前为止所做的代码:

子组件

// 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>

这是我的代码。谁能告诉我问题出在哪里?

【问题讨论】:

    标签: javascript angular typescript angular-reactive-forms angular9


    【解决方案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 个错误。如果set() 方法从header.component.ts 触发一次,则子元素中的ngOnInit 工作正常。但在此之后,如果我路由到任何其他组件并再次回到这里,subscribe 中的 subscribe 中的 ngOnInit 仍然是正确的。有任何解决这个问题的方法吗 ? ngOnDestroy 使用仍然没有变化
    猜你喜欢
    • 2017-02-08
    • 1970-01-01
    • 2018-06-28
    • 1970-01-01
    • 1970-01-01
    • 2019-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多