将数据从父组件传递到子组件(包含反应式表单)以更新该表单的详细信息

Passing data from a parent to child component (containing a reactive form) to update that form's details

我是 Angular 的新手,我希望通过反应式形式实现上述目标。我想我对组件设计和响应式表单模式感到困惑。

问题

  1. 我们第一次加载父组件时,使用 url 参数,它会将值传递给子组件,搜索文本框将具有正确的值。如果我在浏览器上单击返回并且父级更新它的 searchTerm,它再次传递给子组件,它将永远不会更新搜索文本框,因为 child.ngOnInit() 不会再次执行。

  2. 这是否是在子组件中声明了 formGroup 的有效设计?我见过的大多数示例都在父级中声明了一个 formGroup,然后包含一个子组件,该子组件随后具有 1 个或多个 formControls....但这并不意味着现在任何其他想要包含我的子组件的组件现在都必须声明一个formGroup,子组件会显得不那么独立

父视图

<searchBox (search)="onSearchTextEntered($event)" [searchText]="this.searchText"></searchBox>

父组件

  ngOnInit() {
     
     /* 
        1) check url params, execute search, set searchText value that is passed to childComponent
        so it can populate searchBox text 
        
        2) Subscribe to NavigateEnd event of router to catch back/fwd browser click, execute search, set searchText value that is passed to childComponent
        so it can populate searchBox text
     */
  }

子视图

<input type="text" [formControl]="searchTerm">

子组件

@Input() searchText: string;
@Output() search: EventEmitter<string> = new EventEmitter();
searchSection = new FormGroup({
    searchTerm: new FormControl()

ngOnInit() {
this.searchSection.get('searchTerm').setValue(this.searchText);
}
...

我在子组件中使用 formGroup 完全有效。

    1) check url params, execute search, set searchText value that is passed to childComponent so it can populate searchBox text 

为此,您可能需要创建 subject,然后像这样在模板中订阅

<searchBox (search)="onSearchTextEntered($event)" [searchText]="subjectRoutes | async"></searchBox>

在这种情况下,您需要在每次

时更新 this.searchSection.get('searchTerm').setValue(this.searchText)

@Input() searchText: string; 变化。 您可以通过为此 属性 创建 setter 或使用 ngOnChanges 生命周期方法来实现。

或者您可以创建自定义可重用 formControl Custom form controls

@Input 与 setter 函数一起使用,因为 ngOnInit 将在加载组件时仅执行一次。

//Parent component
ngOnInit() {
 this.route.queryParamMap.subscribe(queryParams => {
  this.searchText = queryParams.searchText;
 })
}

<searchBox (search)="onSearchTextEntered($event)" [searchText]="searchText"></searchBox>
//You don't even need `this` keyword in template
//Child component
@Input() set searchText(value: string) {
 //This setter function will execute whenever parent input `searchText` is changed.
 console.log(value); //New value from parent
 this.searchSection.get('searchTerm').setValue(value);
}

您不需要使用 FormGroup,您可以使用单个 formControl

controlSearch=new FormControl()

<input [formControl]="controlSearch">

并在 ngOnInit 中订阅 valueChange 以发出响应

ngOnInit(){
   this.controlSearch.valueChanges.pipe(
      startWith(this.controlSearch.value)
   ).subscribe(res=>{
      this.onSearchTextEntered.emit(res);
   })
}

rxjs 运算符 startWith 使它首先以实际值执行

在Input中使用setter给控件赋值

@Input() set searchText(value){
    this.controlSearch.setValue(value);
}