如何在Angular 8中重新加载或刷新仅子组件

51

我有两个组件,一个是父组件,另一个是子组件。

HTML部分

<div>
  <div class="row col-md-12">
    <div class="col-md-4">
       <!-- Some HTML Code of Parent component over here -->
    </div>
    <div class="col-md-8">
      <child-component></child-component>
    </div>
 </div>
 <button class="button" (click)="reloadOnlyChild($event)">Reload Child</button>
</div>

现在,单击此按钮时,我希望仅重新加载或刷新其唯一子元素。

TS部分

reloadOnlyChild(event){
  // I want to reload the child from here.
}

我在互联网上搜索,发现了Vue或React,但没有找到Angular。


“reload”是什么意思?是让*ngOnInit再次启动吗? - Wandrille
假设,子组件是一个表单。 我已经填写了那个表单。 当我点击按钮时,我正在保存数据,并且我希望它重新加载,以便该表单的所有字段都变为空白和未触及状态。 - Saurabh Singh Rajput
你能贴更多的代码或者最好是创建一个StackBlitz来说明这个问题吗? - robert
6个回答

67

更新子组件的最佳方式是:ngOnChanges()

ngOnChanges():"当指令的任何数据绑定属性发生更改时调用的生命周期钩子。定义一个ngOnChanges()方法来处理这些更改",我们使用这个生命周期钩子来响应@Input()变量的变化。

示例:

import { Component, Input, OnChanges } from "@angular/core";

@Component({
  selector: "child-component",
  templateUrl: "./child-component.html"
})
export class MyComponent implements OnChanges {
  @Input() someInput: string;

  constructor() {}

  ngOnChanges() {
  /**********THIS FUNCTION WILL TRIGGER WHEN PARENT COMPONENT UPDATES 'someInput'**************/
  //Write your code here
   console.log(this.someInput);
  }   
 
}

按以下方式在父组件中使用子组件

<child-component [someInput]="inputValue"></child-component>

如果你正在处理弹出窗口,那么这种情况可能会失败。 - ravipatel
嘿@ravipatel,不会失败,除非你做错了。你的情况是什么? - Arun Saini
我有一个类,我将其传递给一个子组件,该类包含在其内部更改数据的函数,这不是由Angular检测到的更改。因此,我只需在子组件中添加@Input() lastChanged?: Date;,并在本地更新函数中的对象中添加lastChanged?: Date;。将其传递给子组件<child [obj]="obj" [lastChanged]="obj.lastChanged" />,然后子组件的ngOnChanges()方法会被调用。 - Pierre

30

假设你在Child.Component.ts中有一个表格,如果你想从Parent.Component重置它,你可以使用Subject在父子组件之间建立连接。

Parent.Component.html

<child-component [resetFormSubject]="resetFormSubject.asObservable()"></child-component>
<button (click)="resetChildForm()"></button>

Parent.Component.ts

import { Subject } from "rxjs";
resetFormSubject: Subject<boolean> = new Subject<boolean>();

resetChildForm(){
   this.resetFormSubject.next(true);
}

Child.Component.ts

import { Subject } from "rxjs";
@Input() resetFormSubject: Subject<boolean> = new Subject<boolean>();

ngOnInit(){
 this.resetFormSubject.subscribe(response => {
    if(response){
     yourForm.reset();
    // Or do whatever operations you need.
  }
 }
}

通过使用Subject,你可以在每次按钮被点击时从父元素向子元素建立连接。

希望这个答案有所帮助!干杯 :)


18

你可以添加一个输入(Input)来更新组件,或者在子组件中添加一个更新函数(update function),你可以在代码中调用它。使用@ViewChild从父组件调用子组件的update函数。像这样:

( https://stackblitz.com/edit/angular-updatechild ):

子组件:

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

@Component({
   selector: "app-child",
   templateUrl: "./child.component.html",
   styleUrls: ["./child.component.css"] 
})
export class ChildComponent {
   ticks = Date.now().valueOf();

   constructor() {}

   update(): void {
   this.ticks = Date.now().valueOf();
   }
}

父级:

import { Component, OnInit, ViewChild } from "@angular/core";
import { ChildComponent } from "./../child/child.component";

@Component({
 selector: "app-parrent",
 templateUrl: "./parrent.component.html",
 styleUrls: ["./parrent.component.css"]
})
export class ParrentComponent implements OnInit {
  @ViewChild(ChildComponent, { static: false }) childC: ChildComponent;
  showChild: boolean = true;
  constructor() {}

  ngOnInit() {}

  onUpdateChild() {
    this.childC.update();
 }
}

12

我们还可以使用*ngIfsetTimeout来在父组件中重置子组件,而不需要对子组件进行修改。

.template:

.ts:

show:boolean = true

resetChildForm(){
   this.show = false;

   setTimeout(() => {
      this.show = true
    }, 100);
}

当我们无法控制子组件时,例如第三方库组件,这尤其有帮助。


6

我采用了这种方法,觉得它是最容易的方法。根据你的代码;

<!-- ParentComponent.html -->
<div>
  <div class="row col-md-12">
    <!--- Observe; I added something here --->
    <child-component [someValueToGetChanges]="ValueInput"></child-component>
 </div>
</div>

然后在我们的 childComponent 中使用 angularngOnChanges 生命周期钩子。当指令的任何数据绑定属性发生变化时,ngOnChanges 方法将被调用。因此,在您的 childComponent 中,我们将这样做:

export class ChildComponent implements OnChanges {
  @Input() 
  someValueToGetChanges: string;
  
  // this code is called when "someValueToGetChanges" value is changed by "ParentComponent"
  ngOnChanges() {
      // Code here what you want
      console.log(this.someValueToGetChanges);
  }   
  
  constructor() {}
}

希望这对您也有帮助!

0
Suhas Parameshwara的回答很好,但是它缺少了一个取消订阅以防止内存泄漏,这可能会让复制粘贴解决方案的人遇到问题。还有一个多余的Subject创建(它也是一个Observable,而不是Subject),如果你忘记向子组件传递Observable,就会隐藏一个错误。
以下是更完整的解决方案:

Parent.Component.html

<child-component [resetForm]="formResetter.asObservable()"></child-component>
<button (click)="resetChildForm()"></button>

Parent.Component.ts

import { Component } from '@angular/core';
import { Subject } from 'rxjs';

@Component({
  selector: 'app-parent',
  templateUrl: './parent.component.html',
  styleUrls: ['./parent.component.css'],
})
export class ParentClass {

  public formResetter: Subject<boolean> = new Subject<boolean>();

  resetChildForm() {
    this.formResetter.next(true);
 }
}

Child.Component.ts

import { Component, Input, OnDestroy, OnInit } from '@angular/core';
import { Observable } from 'rxjs';

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css'],
})
export class ChildClass implements OnInit, OnDestroy {
  @Input() resetForm: Observable<boolean>;

  private sub: any;

  ngOnInit() {
    this.sub = this.resetForm.subscribe(response => {
    // do whatever operations you need.
    });
  }

  ngOnDestroy(): void {
    this.sub.ngUnsubscribe();
  }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接