2016-03-23 62 views
0

我想弄清楚Angular 2中的交叉组件通信并且现在失败。基本上我有3个组件:一个AddProduct组件,在这种情况下,它是父级,一个CategorySelector组件,它使用服务来填充下拉列表以及一个类别列表,以及一个ProductSelector组件,它将一个类别作为参数并使用下拉列表填充属于所选类别的产品列表。角度2:当组件A更新更新组件B

我想弄清楚的是如何让CategorySelector改变ProductSelector运行所需的功能来获取新的产品列表。

这里是我的代码:

附加product.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> 

附加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() { 

    } 

} 

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

} 
+2

您可以尝试在ProductSelector上实现ngOnChanges生命周期钩子,并在其类别输入属性更改时运行'fetchProducts' - 我认为这会起作用。 – rrjohnson85

+0

@ rrjohnson85我从字面上找到了!这是过去一周的情况?哈哈 – watzon

+0

哈哈,在做类似的事情之前的一周左右,我就偶然发现了它。我需要更深入地探索钩子,我相信他们会比以后更早地派上用场。 – rrjohnson85

回答

1

由于A成分和B是兄弟姐妹,和你想通知B,你有两个选择:

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