【问题标题】:Angular 2: When component A changes update component BAngular 2:当组件 A 更改时更新组件 B
【发布时间】:2016-04-08 03:00:25
【问题描述】:

我正在尝试找出 Angular 2 中的跨组件通信,但现在失败了。基本上我有 3 个组件:一个 AddProduct 组件,在这种情况下是父组件,一个 CategorySelector 组件,它使用服务来填充带有类别列表的下拉列表,以及一个 ProductSelector 组件,它以类别作为参数并填充下拉列表属于所选类别的产品列表。

我想弄清楚的是如何做到这一点,以便在 CategorySelector 更改时 ProductSelector 运行获取新产品列表所需的功能。

这是我的代码:

添加产品.html

<h1 class="ui header">Add product</h1>

<form class="ui form">
  <div class="four wide field">
    <label>Category</label>
    <category-selector (selection)="setCategory($event)" defaultText="Please Choose a Category"></category-selector>
  </div>
  <div class="four wide field" *ngIf="selectedCategory">
    <label>Product</label>
    <product-selector (selection)="setProduct($event)" [category]="selectedCategory" defaultText="Select a Product"></product-selector>
  </div>
</form>

add-product.component.ts

import {Component, OnInit, NgZone} from 'angular2/core';
import {StoreProduct} from './storeproduct.service';
import {Product} from './product.service';
import {CategorySelector} from './category-selector.component';
import {ProductSelector} from './product-selector.component';

declare var __resourcePath: string;

@Component({
    selector: 'add-product',
    templateUrl: __resourcePath + '/html/add-product.html',
    providers: [Product, StoreProduct],
    directives: [CategorySelector, ProductSelector]
})
export class AddProduct {

    public categories: string[];
    public selectedCategory: string;
    public selectedProduct: Product__c;

    constructor(private storeproduct: StoreProduct, private product: Product, private zone: NgZone) {}

    setCategory(selection: string) {
        this.selectedCategory = selection;
    }

    setProduct() {

    }

}

product-selector.component.ts

import {Component, Input, Output, EventEmitter, OnInit} from 'angular2/core';
import {Product} from './product.service';

@Component({
    selector: 'product-selector',
    template: `
        <select #sel (change)="selection.emit(sel.value)" class="ui fluid dropdown">
            <option value="" selected>{{defaultText}}</option>
            <option *ngFor="#product of products" value="{{product}}">{{product.Name}}</option>
        </select>
    `,
    providers: [Product]
})
export class ProductSelector implements OnInit {

    @Output() selection = new EventEmitter();
    @Input() defaultText: string = 'No product selected';
    @Input() category: string;

    private products: Product__c[];

    constructor(private product: Product) {}

  fetchProducts() {
    let source = this.product.fetch(this.category);
        let sub = source.toPromise().then((val: JSForce.SOQLQueryResult<Product__c>) => {
            this.products = val.records;
        });
  }

    ngOnInit(): any {
    this.fetchProducts();
    }

}

category-selector.component.ts

import {Component, Input, Output, EventEmitter, OnInit} from 'angular2/core';
import {StoreProduct} from './storeproduct.service';

@Component({
    selector: 'category-selector',
    template: `
        <form class="ui form">
            <select #sel (change)="selection.emit(sel.value)" class="ui fluid dropdown">
                <option value="" selected>{{defaultText}}</option>
                <option *ngFor="#category of categories" value="{{category}}">{{category}}</option>
            </select>
        </form>
    `,
    providers: [StoreProduct]
})
export class CategorySelector implements OnInit {

    @Output() selection = new EventEmitter();
    @Input() defaultText: string = 'No category selected';

    categories: string[];

    constructor(private sp: StoreProduct) {}

    ngOnInit(): any {

        let source = this.sp.fetchCategories();
        let sub = source.toPromise().then((val: string[]) => {
            this.categories = val;
        });
    }

}

【问题讨论】:

  • 您可以尝试在 ProductSelector 上实现 ngOnChanges 生命周期挂钩,并在其类别输入属性更改时运行 fetchProducts - 我认为这会起作用。
  • @rrjohnson85 我真的发现了!过去一周这是在哪里?!哈哈
  • 哈哈,大约一周前我在做类似的事情时偶然发现了它。我需要更深入地探索这些钩子,我相信它们迟早会派上用场。
  • @rrjohnson85 你知道是否有一种实际的方法可以将事件从 A 发送到 B,而不仅仅是监听变化?
  • 我不确定,但我怀疑您可以使用服务来做到这一点 - 所以它更像是 A 到服务到 B 类型的工作流程,而不是简单的 A 到 B。如果有是另一种方式,我还没有找到,但如果你找到了,请告诉我。

标签: angular


【解决方案1】:

由于组件 A 和组件 B 是同级组件,并且您希望 A 通知 B,您有两种选择:

  • 从 A 向父级发送一个事件/值,然后数据绑定到 B 上的输入属性。如果您需要在值更改时在 B 中运行一些逻辑,请实现生命周期挂钩 ngOnChanges()(正如 @rrhohnson85 已经提到的在评论中)。我不建议在 setter 中触发此逻辑。
  • 使用带有主题或可观察对象的共享服务(@rrhohnson85 在评论中也已提及)。组件 A 将调用服务上的一个方法,该方法在 Subject 或 Observable 上调用 next()。组件 B 将 subscribe() 发送给 Subject 或 Observable 以获取更改/事件的通知。
    有关使用主题的示例,请参阅cookbook
    请参阅这个 SO 问题 Delegation: EventEmitter or Observable in Angular2,了解使用 Observable 的示例。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-12-02
    • 2018-02-20
    • 1970-01-01
    • 1970-01-01
    • 2016-09-06
    • 2016-11-19
    • 1970-01-01
    • 2017-08-22
    相关资源
    最近更新 更多