Angular 2,从不相关的组件更改另一个组件的 View

标签 angular components

我可以从另一个组件更改组件变量的值,如本例中的 console.log() 所示。

我的问题是,尽管变量发生了变化,但第二个组件的 View 没有刷新。

例子:

first.component.ts

import {Component} from '@angular/core';
import {SecondComponent} from './second.component';

@Component({
    selector: 'first',
    template: `
        <h2>First component</h2>
        <button (click)="changeOutside()">Change</button>
    `,
    providers: [SecondComponent]
})
export class FirstComponent {
    constructor(private otherComponent: SecondComponent) {}
    changeOutside() {
        this.otherComponent.change();
    }
}

second.component.ts

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

@Component({
    selector: 'second',
    template: `
        <h2>Second component</h2>
        <div>Pet: {{animal}}</div>
        <button (click)="change()">Change</button>
    `
})
export class SecondComponent {
    animal: string = 'Dog';
    change() {
        this.animal = 'Cat';
        console.log(this.animal);
    }
}

这两个组件完全不相关,来自 DOM 树的不同分支。

我也试过第一个组件发出一个事件,第二个组件订阅它并得到相同的结果,变量改变但 View 不更新。


Günter's suggestion 之后(谢谢),我尝试了下一个解决方案但没有成功。甚至 console.log 也不工作。

first.component.ts

import {Component} from '@angular/core';
import {UpdateService} from './update.service';

@Component({
    selector: 'first',
    template: `
        <h2>First component</h2>
        <button (click)="changeOutside()">Change</button>
    `
})
export class FirstComponent {
    constructor(private updateService: UpdateService) {}
    changeOutside() {
        this.updateService.changeAnimal('Cat');
    }
}

update.service.ts

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

@Injectable()
export class UpdateService {
    // Observable string sources
    private newAnimalSource = new Subject<string>();
    // Observable string streams
    newAnimal$ = this.newAnimalSource.asObservable();

    changeAnimal(animal: string) {
        this.newAnimalSource.next(animal);
    }
}

second.component.ts

import {Component} from '@angular/core';
import {UpdateService} from './update.service';
import {Subscription} from 'rxjs/Subscription';
import {Subject} from 'rxjs/Subject';

@Component({
    selector: 'second',
    template: `
        <h2>Second component</h2>
        <div>Pet: {{animal}}</div>
        <button (click)="change()">Change</button>
    `
})
export class SecondComponent {
    animal: string = 'Dog';
    subscription: Subscription;
    constructor(private updateService: UpdateService) {
        this.subscription = updateService.newAnimal$.subscribe(
            animal => {
                console.log(animal);
                this.animal = animal;
        });
    }
    change() {
        this.animal = 'Cat';
    }
}

已解决

最后,Günter提出的方案在@NgModule中添加UpdateService作为provider后生效app.module.ts

最佳答案

更新

我很确定你的问题的原因是你所期望的

constructor(private otherComponent: SecondComponent) {}

做一些它实际上根本不做的事情。

使用此构造函数,您可以注入(inject)一个与页面中显示的组件无关的 SecondComponent 实例。这就是您的 View 未更新的原因。您没有更新可见组件,而是更新了一个完全不相关的类。

您需要使用不同的策略来获取对其他组件的引用。

最好的方法是根本获取对组件的引用,而是向两者注入(inject)共享服务并使用可观察对象进行通信。

有关详细信息,请参阅 this official angular 2 cookbook

原创

如果两个组件“完全不相关”,我认为这意味着它们来自单独引导的模块,因此位于同一页面上的不同 Angular2 应用程序中。

在这种情况下,这些组件在不同的区域中运行,click 事件只会在调用组件中引起更改检测,而不会在被调用组件中引起更改检测。

您需要在被调用方中显式调用更改检测来更新 View 。比如喜欢

import {Component, ChangeDetectorRef} from '@angular/core';

@Component({
    selector: 'second',
    template: `
        <h2>Second component</h2>
        <div>Pet: {{animal}}</div>
        <button (click)="change()">Change</button>
    `
})
export class SecondComponent {
    constructor(private cdRef:ChangeDetectorRef){}

    animal: string = 'Dog';
    change() {
        this.animal = 'Cat';
        console.log(this.animal);
        this.cdRef.detectChanges();
    }
}

import {Component, NgZone} from '@angular/core';

@Component({
    selector: 'second',
    template: `
        <h2>Second component</h2>
        <div>Pet: {{animal}}</div>
        <button (click)="change()">Change</button>
    `
})
export class SecondComponent {
    constructor(private zone:NgZone){}

    animal: string = 'Dog';
    change() {
        this.zone.run(() => {
          this.animal = 'Cat';
          console.log(this.animal);
        });
    }
}

关于Angular 2,从不相关的组件更改另一个组件的 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39722768/

相关文章:

c# - 颠倒的垂直进度条?

reactjs - 通过在 React 中更改父组件的 Props 来更新子组件

delphi - 如何从命令行安装Delphi组件包?

java - Java 中最好的 "closable TabbedPane"组件是什么?

javascript - 光标在 ngModelChange Angular/Typescript 上结束时出现问题

css - 如何并排对齐 p-table 和 p-chart 元素

angular - 如何强制在 angular2 中执行自定义过滤管道

laravel - 如何在 Laravel 5.4 中加载 Vue 组件?

angular - 刷新 Handsontable Angular 4

angular - 通过组件属性为您的 css 类添加动态命名空间对性能/加载是否不利?