如何重新加载当前的Angular 2组件

7
如何在Angular 2中重新加载同一组件?
以下是我的代码:
import { Component, OnInit, ElementRef, Renderer } from '@angular/core';
import { Router, ActivatedRoute, Params } from '@angular/router';
import { productModel } from '../_models/index';
import { categoryListService } from '../_services/index';

@Component({
  selector: 'app-product',
  templateUrl: 'product.component.html',
  styleUrls: ['product.component.css']
})
export class productComponent implements OnInit {
  uidproduct: productModel;
  param: number;
  constructor(
    private elementRef: ElementRef,
    private route: ActivatedRoute,
    private router: Router,
    private categoryListService: categoryListService) { }

  ngOnInit() {
    this.route.params.subscribe(product => {
      console.log('logging sub product obj', product);
    });
    this.uidproduct = JSON.parse(sessionStorage.getItem('product'));
    var s = document.createElement("script");
    s.type = "text/javascript";
    s.src = "http://this/external/script/needs/to/be/loaded/each/time.js";
    this.elementRef.nativeElement.appendChild(s);
  }
  nextproduct(){ 
    let i = this.uidproduct.order;
    this.categoryListService.findNextproduct(this.uidproduct);
    this.param = ++i;
    this.router.navigate([`/product/${this.param}`]);
  }
}

nextproduct() 是在模板中绑定到一个点击事件的函数。

uidproduct 是一个 JSON 对象,有许多属性,我正在使用 {{uidproduct.classname}} 更新 DOM。

我在模板中像这样使用它:

<div id="selected-product" class="{{uidproduct.classname}}">

当我点击 <button (click)="nextproduct()"> 时,它会改变DOM中的类属性,但我需要重新加载组件以便外部脚本生效。


我认为组件重新加载选项永远不会是一个好选择,你说的“我需要重新加载组件才能使外部脚本生效”是什么意思? - Pankaj Parkar
外部脚本正在针对特定的DOM元素类属性,并将特定产品呈现到DOM中。干杯! - Dave
什么外部脚本? - jonrsharpe
@Dave,您不能从模板中加载外部脚本(这可能会导致安全威胁),我建议您阅读此问题 - Pankaj Parkar
@PankajParkar 当ngOnint被触发时它可以工作,你有任何关于如何重新加载组件的建议吗?谢谢 - Dave
2
@PankajParkar,我已经从模板中删除了外部脚本,但如果有任何重新加载组件的更新,那就太棒了! - Dave
2个回答

22

您可以使用*ngIf来重新渲染模板的内容:

@Component({
  selector: '...',
  template: `
<ng-container *ngIf="!rerender">
 template content here
</ng-container>`
})
export class MyComponent {
  rerender = false;
  constructor(private cdRef:ChangeDetectorRef){}
  doRerender() {
    this.rerender = true;
    this.cdRef.detectChanges();
    this.rerender = false;
  }
}

3
很棒的技巧,就像这样,我搜索了很多东西并尝试了许多合法的步骤,但都没有成功。在我的语言中,这叫做“JUGAD”。 - bharatpatel

2

我不明白为什么需要重新加载组件。如果您绑定了uidproduct的各个字段,那么重新加载应该会刷新组件中显示的值。因此,重新加载组件除了增加开销之外没有任何作用。

如果您认为还有其他很好的原因没有提到而需要这样做,那么请按照以下步骤操作:

  1. 导航到另一个(可能是空白)组件。
  2. 直接返回。

问题在于您需要等待第一次导航完成后再执行第二次导航。

在您的组件中,导入NavigationEnd:

import { Router, NavigationEnd } from '@angular/router';

然后在构造函数中订阅它:

constructor(private thingService: ThisThingService, private router: Router) { 
   router.events.subscribe(event => {
    if (event instanceof NavigationEnd) {
      if (event.url === '/blank') {
        this.router.navigate(['product']); 
      }
    }
  });

请注意,我等待NavigationEnd事件发生,然后检查是否要路由到我的空白组件。如果是空白组件的路径,我会导航回产品页面。如果您确实需要传递该ID,请将其存储在对象上并在此处添加。

nextproduct()中,不要路由到产品页面,而是导航到blank

this.router.navigate(['blank']);

这样就可以完美地重新加载您的组件。

但我故意留下了一个简单的问题:构造函数中的subscribe调用将在每次重新加载时执行。因此,作为读者的练习,请将其从构造函数中取出并创建一个良好的服务,或将其移动到应用程序组件的构造函数中,或者移动到路由模块中或其他适合您的位置。


谢谢,它正在工作,尽管逻辑不是很直接。@Günter Zöchbauer的答案没有更新我的服务,但它确实在我的组件中更新了所有数据 :) - ruucm

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