【问题标题】:How to update data on change when using TemplateRef from parent component in child in Angular如何在Angular的子组件中使用来自父组件的TemplateRef时更新更改数据
【发布时间】:2020-01-20 15:15:33
【问题描述】:

我有一个子组件,它从父组件渲染模板,例如 embededView。

exports class ParentComponent {
   public someProp: string;

   ngOnInit() {
      this.someHttpFunc();
   }

   public someHttpFunc() {
      // make some http call and update this.someProp
   }
}
exports class ChildComponent {
   @Input() someRef: TemplateRef<any>
   @ViewChild("content", { read: ViewContainerRef }) contentRef: ViewContainerRef;

   ngOnInit() {
     this.contentRef.createEmbeddedView(someRef);
   }
}

我的 parent.component.html:

<child someRef="template"></child>
<ng-template #template>

  <div>{{ someProp }}</div>
</ng-template>

我的 child.component.html

<div #content></div>

问题是当someHttpFunc()中的http调用完成时,子组件中someProp的结果不会自动更新。当我为this.contentRef.createEmbeddedView(someRef); 设置超时时 一切正常,但绝对不是一个好的解决方案

【问题讨论】:

  • 使用 observable 代替 {{ someProp$ | async }}
  • 我已经在使用 observable,someProp 是属性名称,将在.subscribe() 中更新
  • 欢迎使用 Angular 中的更改检测。这是一个更广泛的主题,需要了解它的工作原理,您应该首先了解这一点,然后才能了解组件之间交叉引用模板的更多优势技术。当 observable 发出一个值时,async 管道会将 view 标记为脏。这是我为您准备的快速修复,因为猜猜谁的视图需要更新? ChildComponentasync 管道的 instance 运行的地方。 ParentComponent 不呈现模板。所以没有改变任何表达式来标记视图脏。

标签: angular


【解决方案1】:

尝试这样做:

parent.component.ts

exports class ParentComponent {
   public someProp$: Observable<string>;
   private propSource: Subject<string>;

   constructor() {
     this.propSource = new Subject();
     this.someProp$ = this.propSource.asObservable();
   }
   ngOnInit() {
      this.someHttpFunc();
   }

   public someHttpFunc() {
      // psuedo code for http calls
      httpCall.subscribe(() => {
        const newValue = 'x'; // here it's the new value of your props
        this.propSource.next(newValue)
      });
   }
}

parent.component.html

<child someRef="template"></child>
  <ng-template #template>

  <div>{{ someProp$ | async }}</div>
</ng-template>

【讨论】:

    【解决方案2】:

    也许你可以尝试使用 setter ,比如这些代码

    exports class ChildComponent {
      @Input()
      set someRef(newTemplate: TemplateRef < any > ) {
        if (!newTemplate) {
          return;
        }
    
        this.contentRef.createEmbeddedView(someRef);
    
      }
    
      @ViewChild("content", {
        read: ViewContainerRef
      }) contentRef: ViewContainerRef;
    }

    【讨论】:

      猜你喜欢
      • 2019-07-28
      • 2021-02-10
      • 2018-04-22
      • 2019-02-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-08
      • 2017-11-03
      相关资源
      最近更新 更多