Angular 角度2:组件A更改时更新组件B
我试图找出Angular 2中的跨组件通信,但现在失败了。基本上我有3个组件:一个AddProduct组件(在本例中为父组件)、一个CategorySelector组件(使用服务用类别列表填充下拉列表)和一个ProductSelector组件(使用类别作为参数并用属于所选类别的产品列表填充下拉列表) 我想弄清楚的是如何使CategorySelector更改时,ProductSelector运行获取新产品列表所需的函数 这是我的密码: add-product.htmlAngular 角度2:组件A更改时更新组件B,angular,Angular,我试图找出Angular 2中的跨组件通信,但现在失败了。基本上我有3个组件:一个AddProduct组件(在本例中为父组件)、一个CategorySelector组件(使用服务用类别列表填充下拉列表)和一个ProductSelector组件(使用类别作为参数并用属于所选类别的产品列表填充下拉列表) 我想弄清楚的是如何使CategorySelector更改时,ProductSelector运行获取新产品列表所需的函数 这是我的密码: add-product.html <h1 class="
<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-selector.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() {
}
}
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();
}
}
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;
});
}
}
import{Component,Input,Output,EventEmitter,OnInit}来自'angular2/core';
从“./Product.service”导入{Product};
@组成部分({
选择器:“产品选择器”,
模板:`
{{defaultText}}
{{product.Name}
`,
供应商:[产品]
})
导出类ProductSelector实现OnInit{
@Output()selection=neweventemitter();
@Input()defaultText:string='未选择任何产品';
@Input()类别:字符串;
私人产品:Product_u_c[];
构造函数(私有产品:产品){}
获取产品(){
让source=this.product.fetch(this.category);
让sub=source.toPromise().then((val:JSForce.SOQLQueryResult)=>{
this.products=val.records;
});
}
ngOnInit():任何{
这是fetchProducts();
}
}
类别选择器.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() {
}
}
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();
}
}
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;
});
}
}
import{Component,Input,Output,EventEmitter,OnInit}来自'angular2/core';
从“./StoreProduct.service”导入{StoreProduct};
@组成部分({
选择器:“类别选择器”,
模板:`
{{defaultText}}
{{category}}
`,
提供者:[存储产品]
})
导出类CategorySelector实现OnInit{
@Output()selection=neweventemitter();
@Input()defaultText:string='未选择任何类别';
类别:字符串[];
构造函数(私有sp:StoreProduct){}
ngOnInit():任何{
让source=this.sp.fetchCategories();
让sub=source.toPromise()。然后((val:string[])=>{
this.categories=val;
});
}
}
由于组件A和组件B是兄弟,并且您希望A通知B,因此您有两种选择:
- 将事件/值从A向上发送到父级,然后数据绑定到B上的输入属性。如果需要在值更改时在B中运行某些逻辑,请实现lifecycle hook
(注释中已经提到@rrhohnson85)。我不建议在setter内部触发此逻辑ngOnChanges()
- 将共享服务(@rrhohnson85在评论中也提到过)与主题或可观察对象一起使用。组件A将调用服务上的一个方法,该方法调用主题或可观察对象上的
。组件B将next()
订阅受试者或可观察者,以获得变更/事件的通知subscribe()
有关使用主题的示例,请参见
查看这个SO问题,例如,使用可观察对象的示例
fetchProducts
——我认为这会起作用。@rrjohnson我刚刚发现了这一点!这一周都在哪里?!哈哈哈,我只是在一周前做类似的事情时偶然发现的。我需要更深入地探索钩子,我相信它们迟早会派上用场。@rrjohnson 85你知道有没有一种真正的方法可以将事件从A发送到B,而不仅仅是倾听变化?我不确定,但我怀疑你可以通过服务来实现这一点,因此这将是一个从a到B的工作流,而不仅仅是从a到B的工作流。如果有其他方法,我还没有找到它,但是如果你找到了,请告诉我。