Reputation: 43
I'm doing a twitter moderator in Angular. For that I have a list of tweets, each tweet being like this:
export class Tweet{
id: number;
text: string;
image: string;
profileImage: string;
name: string;
username: string;
date: number;
state: TweetState;
}
TweetState is an enum with 4 states, new, approved, favorite and denied.
I want to show them each one in a different tab, and when the user click on the corresponding button, change the state and therefor change the tab where it is.
This is my html:
<mat-tab-group mat-selected="selectedTab" mat-border-bottom mat-autoselect mat-swipe-content>
<mat-tab label="NEW" class="tab" fxLayout="row">
<app-tweet *ngFor="let tweet of campaign.tweets | new" [tweet]="tweet"></app-tweet>
</mat-tab>
<mat-tab label="FAVORITE" class="tab">
<app-tweet *ngFor="let tweet of campaign.tweets | favorite" [tweet]="tweet"></app-tweet>
</mat-tab>
<mat-tab label="APPROVED" class="tab">
<app-tweet *ngFor="let tweet of campaign.tweets | approved" [tweet]="tweet"></app-tweet>
</mat-tab>
<mat-tab label="DENIED" class="tab">
<app-tweet *ngFor="let tweet of campaign.tweets | denied" [tweet]="tweet"></app-tweet>
</mat-tab>
</mat-tab-group>
The pipes work fine, at least at the initial state. When I click the button to change the state, the state changes correctly but it doesn't switches tab.
I imagine that the *ngFor directive runs when the DOM is created and I should remove it from one place and add it on the other manually. What is the best approach? An Observable?
This is the Tweet template
<mat-card class="tweet">
<mat-card-header>
<img matCardAvatar src="{{tweet.profileImage}}" alt="{{tweet.username}}">
<mat-card-title>{{tweet.name}}</mat-card-title>
<mat-card-subtitle>{{tweet.username}}</mat-card-subtitle>
</mat-card-header>
<img mat-card-image src="{{tweet.image}}" alt="{{tweet.username}}">
<mat-card-content>
<p>
{{tweet.text}}
</p>
<p>
{{tweet.state}}
</p>
</mat-card-content>
<mat-card-actions>
<div fxFlex="auto" fxLayout="row" fxLayoutAlign="space-around center">
<span class="material-icons unselectable" (click)="setApproved()">thumb_up</span>
<span class="material-icons unselectable" (click)="setDenied()">thumb_down</span>
<span class="material-icons unselectable" (click)="setFavorite()">star</span>
</div>
</mat-card-actions>
</mat-card>
Upvotes: 0
Views: 320
Reputation: 4831
If your issue is the data update, the reason why it isn't updating is because you didn't tell Angular that you have altered the state of tweets
.
Where you have *ngFor="tweet of campaign.tweets"
, you should change over to an observable. *ngFor="tweet of (tweets$ | async)"
where in your component or the parent component generate the Observable on the fly.
For example in the same component for this template you could do.
//the component boiler plate stuff
export class MyTweetComponent implements OnInit, OnChanges {
@Input() tweets$: Observable<Tweet[]> //parse your campaign object up front.
ngOnInit() {} // initialize tweets$ here if you got a service or something.
ngOnChanges() {} //tell angular to detect changes (you may add additional logic here for handling tweets)
constructor() { } //if you have a service to grab tweets you can inject it here
}
The async
pipe will handle the subscription for you, all you have to do is in the component pass the observable of tweets down from parent or initialize it.
Upvotes: 1