Reputation:
Hi I'm working on a webpage in Angular and want to add a feature that can allow the User to write Comments and mark them with a Star if they want. Here is the HTML
part:
<ul>
<li class="realitive" *ngFor="let comment of comments">
{{ comment }}
<nb-icon pack="font-awesome" class="fa-star absulute" [ngClass]="{ 'fas': isFavorite,' far': !isFavorite}" (click)="onClick()"></nb-icon>
</li>
</ul>
and here the Logic behind this:
comments: string[] = [];
@Input("isFavorite") isFavorite: boolean;
@Output("change") change= new EventEmitter();
onClick() {
this.isFavorite = !this.isFavorite;
this.change.emit({ newValue: this.isFavorite });
}
addComment() {
this.dialogService.open(CommentComponent)
.onClose.subscribe(comment => comment && this.comments.push(comment));
}
NOTE: the dialogServis is from Nebular
this is working fine but if I add more than One Comment for testing and click on the star Both are getting active how can I tweak the code so they get change Separately
Upvotes: 0
Views: 376
Reputation: 13129
@code-gorrila is right, if you can have one favorite comment per item. If every comment can be a favorite, though, you need to store isFavorite
as a property of comment:
interface IComment {
comment: string;
isFavorite: boolean;
}
comments: IComment[] = [];
@Output("change") comments = new EventEmitter();
onClick(comment) {
comment.isFavorite = !comment.isFavorite;
this.change.emit(this.comments);
}
addComment() {
this.dialogService.open(CommentComponent)
.onClose.subscribe(comment => comment && this.comments.push({ comment, isFavorite: false }));
}
<ul>
<li class="realitive" *ngFor="let comment of comments">
{{ comment.comment }}
<nb-icon pack="font-awesome" class="fa-star absulute" [ngClass]="{ 'fas': comment.isFavorite,' far': !comment.isFavorite}" (click)="onClick(comment)"></nb-icon>
</li>
</ul>
Upvotes: 0
Reputation: 758
This response is based on angular best practices: smart and dummy components
You could create two components
comment-box-component
: it contain the input and comment-component
.comment-component
: it contain only comment text and star state.comment-component
It has the input (commment text) and output (emit to parent favorite state has change)
On typescript file.
@Input() isFavorite: boolean;
@Output() favorite: EventEmitter<boolean> = new EventEmitter();
selectAsFavorite() {
this.favorite.emit(true);
}
unselectAsFavorite() {
this.favorite.emit(false);
}
comment-box-component
Its a container that listen for comment events (favorite)
On HTML file.
<input type="text"/>
<ng-container *ngFor="let comment of comments">
<comment-component [comment]="comment" (favorite)="handleFavoriteState($event, comment.id)">
</ng-container>
On typescript file.
comments = [{id: 1, text: 'hi', favorite: false}, {id: 2, text: 'bye', favorite: false}] // They are just examples
handleFavoriteState(favorite: boolean, commentId: string) {
// this isn't the best performance approach is just examplenary
this.comment = this.comments.map(comment => {
if (comment.id === commentId) {
comment.favorite = favorite;
}
return comment;
});
}
I suggest to review about smart and dummy components. It's an angular best practice.
Upvotes: 0
Reputation: 2418
The problem is that you have only 1 isFavorite switch on the same level of your comments variable. So if it is true, all your comments will be favorites logic-wise.
The simplest solution would be store the position of the favorite comment instead of just a boolean flag.
So in the template you would do:
<li class="realitive" *ngFor="let comment of comments; index as i">
<nb-icon pack="font-awesome" class="fa-star absulute" [ngClass]="{ 'fas': favoriteComment === i,' far': favoriteComment !== i}" (click)="onClick(i)"></nb-icon>
</li
In your component you would then store the index of the favorite comment:
@Input("favoriteComment") favoriteComment: number;
@Output("change") change= new EventEmitter();
onClick(index: number) {
this.isFavorite = index;
this.change.emit({ newValue: this.favoriteComment });
}
This solution is fine for playing around with it, but for a production app you might want to handle it differently:
Upvotes: 1