我使用输入绑定将产品从父组件传递到子组件,并且它在第一次调用子组件时起作用。我希望每次在父级中修改时,对filterProduct()中的产品的更改都会反映在子级中,但这种情况不会发生。我该如何实现这一目标。
父模板:
<p>NORMAL! Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aperiam et explicabo iusto nemo nihil. Dicta dignissimos eius itaque nemo vero? Consequuntur ducimus hic ipsum nemo nesciunt, quia recusandae sapiente voluptate!</p>
<p class=unselectable>UNSELECTABLE! Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aperiam et explicabo iusto nemo nihil. Dicta dignissimos eius itaque nemo vero? Consequuntur ducimus hic ipsum nemo nesciunt, quia recusandae sapiente voluptate!</p>
<p class="us-none">USER SELECT NONE! Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aperiam et explicabo iusto nemo nihil. Dicta dignissimos eius itaque nemo vero? Consequuntur ducimus hic ipsum nemo nesciunt, quia recusandae sapiente voluptate!</p>
<p class="pe-none">POINTER EVENTS NONE! Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aperiam et explicabo iusto nemo nihil. Dicta dignissimos eius itaque nemo vero? Consequuntur ducimus hic ipsum nemo nesciunt, quia recusandae sapiente voluptate!</p>
父组件:
<div class="container-fluid">
<div class="col-sm-9">
<app-product-card [products]=products></app-product-card>
</div>
子组件:
@Component({
selector: 'app-appliances-product-card',
moduleId: module.id,
templateUrl: 'appliances-product-card.component.html'
})
export class AppliancesProductCardComponent implements OnInit{
products: Product[];
filterProduct(filter) {
this.products = this.filteredProducts;
}
}
答案 0 :(得分:3)
以下是可能适用于你的东西:
https://plnkr.co/edit/S47fBh2xdT1gp2zrznk4?p=preview
父组件和子组件都将使用服务来获取数据,而不是将数据从父组件传递到子组件。
父组件:
import { Component, OnInit } from '@angular/core';
import { Product } from './product'
import { ProductsService } from './products.service';
@Component({
selector: 'app-appliances-product-card',
template: `
<div class="container-fluid">
<button (click)="filterProduct('Type 1')">Filter Type 1</button>
<button (click)="filterProduct('')">Clear Filter</button>
<div class="col-sm-9">
<app-products-card></app-products-card>
</div>
</div>
`
})
export class AppliancesProductCardComponent implements OnInit {
products: Product[];
constructor(private _productsService: ProductsService){ }
filterProduct(type: string) {
this.products = this._productsService.filterProduct(type);
}
ngOnInit() {
this.products = this._productsService.getAllProducts();
}
}
子组件:
import { Component, OnInit, Input } from '@angular/core';
import { Product } from './product';
import { ProductsService } from './products.service';
@Component({
selector: 'app-products-card',
template: `
<h1>Product Card</h1>
<div *ngFor="let product of products">{{product.name}} - {{product.type}}</div>
`
})
export class ProductsCardComponent implements OnInit {
constructor(private _productsService: ProductsService){ }
ngOnInit() {
this.products = this._productsService.getAllProducts();
this._productsService.filteredProducts.subscribe(products => {
console.log(products);
this.products = products
});
}
}
服务:
import { EventEmitter, Injectable } from '@angular/core';
import { Product } from './product';
export class ProductsService {
filteredProducts = new EventEmitter<Product[]>;
private products: Product[] = [
{ id: 1, name: 'Product 1', price: 10.50, type: 'Type 1' },
{ id: 2, name: 'Product 2', price: 15.50, type: 'Type 1' },
{ id: 3, name: 'Product 3', price: 1.50, type: 'Type 2' },
{ id: 4, name: 'Product 4', price: 100.50, type: 'Type 3' }
];
getAllProducts(): Product[] {
return this.products.slice();
}
filterProduct(type: string): Product[]{
let filteredProducts = this.products.filter(p => !type || p.type == type).slice();
this.filteredProducts.emit(filteredProducts);
}
}
当我第一次开始编写角度应用程序时,我遇到了类似的问题。始终将数据从父组件传递到子组件不是编写应用程序的可管理方式。特别是如果它是一个包含太多嵌套组件的大型应用程序。
在这个例子中,我使用服务和事件发射器(角度框架的一部分)来为子组件和父组件提供相关数据。
改进代码的一种方法是使用rxjs。这就是角度事件发射器在场景后面使用的内容。
更高级的解决方案是使用ngrx / store(针对Angular的redux库)。这特别适合大型应用。
无论您选择哪种解决方案,我们的想法都是有一个地方来维护应用程序的状态并避免过多地嵌套数据。
答案 1 :(得分:1)
如果您希望子组件对父组件中的更改做出反应,则需要使用ngOnChanges()
中的SimpleChange
实施@angular/core
。详细的文档可以在Angular - linkComponent Interaction Page找到,但主要的想法用两个代码表示:
子组件
import { Component, Input, OnChanges, SimpleChange } from '@angular/core';
@Component({
selector: 'version-child',
template: `
<h3>Version {{major}}.{{minor}}</h3>
<h4>Change log:</h4>
<ul>
<li *ngFor="let change of changeLog">{{change}}</li>
</ul>
`
})
export class VersionChildComponent implements OnChanges {
@Input() major: number;
@Input() minor: number;
changeLog: string[] = [];
ngOnChanges(changes: {[propKey: string]: SimpleChange}) {
let log: string[] = [];
for (let propName in changes) {
let changedProp = changes[propName];
let to = JSON.stringify(changedProp.currentValue);
if (changedProp.isFirstChange()) {
log.push(`Initial value of ${propName} set to ${to}`);
} else {
let from = JSON.stringify(changedProp.previousValue);
log.push(`${propName} changed from ${from} to ${to}`);
}
}
this.changeLog.push(log.join(', '));
}
}
父组件
import { Component } from '@angular/core';
@Component({
selector: 'version-parent',
template: `
<h2>Source code version</h2>
<button (click)="newMinor()">New minor version</button>
<button (click)="newMajor()">New major version</button>
<version-child [major]="major" [minor]="minor"></version-child>
`
})
export class VersionParentComponent {
major = 1;
minor = 23;
newMinor() {
this.minor++;
}
newMajor() {
this.major++;
this.minor = 0;
}
}
答案 2 :(得分:0)
您可以利用共享服务。它可以包含要订阅的数据和可观察数据,以便在数据更新时得到通知。
服务
@Component({
selector: 'my-component1',
template: `
<ul>
<li *ngFor="#item of list">{{item.name}}</li>
</ul>
`
})
export class MyComponent1 {
constructor(private service:ListService) {
this.service.list1Event.subscribe(data => {
this.list = data;
});
}
}
组件
Sub Create_Zip()
Dim FSO As FileSystemObject
Dim objFile As File
Dim myFolder
Dim strFilename As String
Const zipDir As String = "\\...\Zip Test"
Set FSO = New FileSystemObject
Set myFolder = FSO.GetFolder(zipDir)
For Each objFile In myFolder.Files
strFilename = objFile.name
new_strFilename = Replace(strFilename, ".xlsx", ".zip")
Name zipDir & "\" & strFilename As zipDir & "\" & new_strFilename
Next objFile
End Sub
答案 3 :(得分:0)
使用的解决方案: 使用父组件中指向子组件中的属性的@ViewChild装饰器声明变量。
@Component({ 选择器:'app-appliances-product-card', moduleId:module.id, templateUrl:'appliances-product-card.component.html' })
export class AppliancesProductCardComponent implements OnInit{
products: Product[];
@ViewChild(ProductCardComponent )
private productCardComponent : ProductCardComponent;
filterProduct(filter) {
this.products = productCardComponent.product;
}
}
答案 4 :(得分:0)