角度2:当组件A更改更新组件B时

时间:2016-03-23 00:01:35

标签: angular

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

我想弄清楚的是如何使它成为当CategorySelector改变时,ProductSelector运行获取新产品列表所需的功能。

这是我的代码:

附加product.html

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.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();
    }

}

产品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;
        });
    }

}

类别的selector.component.ts

{{1}}

1 个答案:

答案 0 :(得分:2)

由于组件A和组件B是兄弟姐妹,并且您希望A通知B,因此您有两种选择:

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