我正在从头开始学习Angular。这个主题非常初学者,如果问题是基本的,请原谅我。 我正在学习嵌套组件如何通过使用Output()装饰器引发事件将数据发送到容器组件。 Start组件是名为product list component的容器组件内的嵌套组件。 当用户点击任何评级星时,容器组件的标题应该更改。 但似乎事件不是从星组件(嵌套组件)引发到产品列表组件(容器组件)。 这是我的代码:
star.component.html:
<div class="crop"
[style.width.px]="starWidth"
[title]="rating"
(click)="onClick()">
<div style="width: 86px" >
<span class="glyphicon glyphicon-star"></span>
<span class="glyphicon glyphicon-star"></span>
<span class="glyphicon glyphicon-star"></span>
<span class="glyphicon glyphicon-star"></span>
<span class="glyphicon glyphicon-star"></span>
</div>
star.component.ts
import { Component, OnChanges, SimpleChanges, Input, EventEmitter, Output } from "@angular/core";
@Component({
selector: 'pm-start',
templateUrl: './star.component.html',
styleUrls: ['./star.component.css']
})
export class StarComponent implements OnChanges {
@Input() rating: number;
starWidth : number;
@Output() ratingClicked: EventEmitter<string> = new EventEmitter<string>();
ngOnChanges(changes: SimpleChanges): void {
this.starWidth = this.rating * 86/5;
}
onClick():void{
console.log("stars are clicked");
this.ratingClicked.emit(`The rating ${this.rating} was clicked`);
}
}
product_list.component.html
<div class='panel panel-primary'>
<div class='panel-heading'>
{{pageTitle}}
</div>
<div class='panel-body'>
<div class='row'>
<div class='cpl-md-2'>Filter by:</div>
<div class='col-md-4'>
<input type="text" [(ngModel)] = 'listFilter' />
</div>
</div>
<div class='row'>
<div class='col-md-6'>
<h3> Filter By: {{listFilter}}</h3>
</div>
</div>
<div class='table-responsive'>
<table class='table' *ngIf='products && products.length'>
<thead>
<tr class="firstRow">
<th>
<button class='btn btn-primary'
(click) = 'toggleImage()'>
{{imageShow ? 'Hide' : 'Show'}} Image
</button>
</th>
<th>
Product
</th>
<th>
Code
</th>
<th>
Available
</th>
<th>
Price
</th>
<th>
5 Start Rating
</th>
</tr>
</thead>
<tbody>
<tr *ngFor='let product of filteredProducts'>
<td><img
*ngIf = 'imageShow'
[src]='product.imageUrl' [title]='product.productName'
[style.width.px] = 'imageWith' [style.height.px] = 'imageHeight'></td>
<td>{{product.productName}}</td>
<td>{{product.productCode | lowercase | covertToSpaces:'-'}}</td>
<td>{{product.releaseDate}}</td>
<td>{{product.price | currency:'USD': true :'1.2-2'}}</td>
<td><pm-start [rating]='product.starRating' (ratingClikced)='onRatingClicked($event)'></pm-start></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
product_list.component.ts
import {Component} from "@angular/core"
import { IProduct } from "./product";
@Component({
selector: 'pm-products',
templateUrl: './product-list.component.html',
styleUrls:['./product-list.component.css'],
})
export class ProductListComponent{
pageTitle: string = 'Product List' ;
imageWith: number = 40;
imageHeight: number = 40;
imageShow : boolean = false;
_listFilter : string ;
get listFilter():string {
return this._listFilter;
}
set listFilter(value:string) {
this._listFilter = value;
this.filteredProducts = this._listFilter ? this.performFilter (this._listFilter) : this.products;
}
filteredProducts :IProduct[];
products: IProduct[] = [
{
"productId": 1,
"productName": "Leaf Rake",
"productCode": "GDN-0011",
"releaseDate": "March 19, 2016",
"description": "Leaf rake with 48-inch wooden handle.",
"price": 19.95,
"starRating": 3.2,
"imageUrl": "http://openclipart.org/image/300px/svg_to_png/26215/Anonymous_Leaf_Rake.png"
},
{
"productId": 2,
"productName": "Garden Cart",
"productCode": "GDN-0023",
"releaseDate": "March 18, 2016",
"description": "15 gallon capacity rolling garden cart",
"price": 32.99,
"starRating": 4.2,
"imageUrl": "http://openclipart.org/image/300px/svg_to_png/58471/garden_cart.png"
}
];
constructor(){
this.filteredProducts = this.products;
this._listFilter = 'cart';
}
onRatingClicked(someValue:string):void{
console.log("some body passed data form");
this.pageTitle = "Product List " + someValue;
}
toggleImage ():void{
this.imageShow = !this.imageShow;
};
performFilter (filter:string){
//
filter = filter.toLocaleLowerCase();
return (this.products.filter((product:IProduct) => product.productName.toLocaleLowerCase().indexOf(filter) != -1));
}
}