I have three components. A parent and two children.
One child (the add-friend) wants to update the parents view. So i created the method receiveReloadFriendLists().
I let the method write me an info into the console. So this works fine.
But the view don't gets updated. Now there should be a list of friends. What do i need to do for this?
I don't want to reload the page, because there is an animation running. Which would get killed.
I am sure i missed something in the parent or did something wrong.
I would be happy for help or links to a solution. I followed the first answer of this question But it didn't fullfil my question.
Parent:
@Component({
selector: 'app-friends',
templateUrl: './friends.component.html'
})
export class FriendsComponent implements OnInit {
requested$: Observable<RelationResponse[]>;
requested: RelationResponse[] = [];
constructor(
private store: Store,
private router: Router,
private appStore: Store<AppState>,
private _fb: FormBuilder
) {
this.requested$ = this.store.select(selectRequestedRelationResponse);
}
ngOnInit(): void {
this.getRequestedRelations();
}
private getRequestedRelations() {
this.store.dispatch(invokeFindRequestedRelations({
userId: StorageUtil.getUserId(),
relationStatusRequest: RelationStatusRequest.REQUESTED
})
);
this.appStore.pipe(select(selectAppState)).subscribe((appState) => {
if (ApiUtil.ifApiStatusIsSuccessReset(appState, this.appStore)) {
this.requested$.subscribe((relationResponses) => {
this.requested = relationResponses;
})
}
}
);
}
receiveReloadFriendLists() {
console.log("reload");
this.getRequestedRelations();
}
}
Parent html:
<app-add-friend (reloadRelationsEvent)="receiveReloadFriendLists()" class="p-0"></app-add-friend>
<app-relation-list class="p-0"
[show]=hasFriendRequests()
showHeadline="Friend requests"
noShowHeadline="No Friend requests"
[relations]="requested"
[enableAccept]="true"
[enableBlock]="true"
[enableDelete]="true"></app-relation-list>
Child - Add Friend
@Component({
selector: 'app-add-friend',
templateUrl: './add-friend.component.html'
})
export class AddFriendComponent {
@Output() reloadRelationsEvent = new EventEmitter<void>();
@ViewChild('sendFriendRequestCallout') sendFriendRequestCallout!: CalloutComponent;
addFriendForm: FormGroup;
constructor(private _fb: FormBuilder,
private store: Store) {
this.addFriendForm = this.createAddFriendForm();
}
public createAddFriendForm(): FormGroup {
...
}
sendFriendRequest() {
....
}
reloadFriendLists() {
this.reloadRelationsEvent.emit();
}
}
Child - Show Friends
@Component({
selector: 'app-relation-list',
templateUrl: './relation-list.component.html'
})
export class RelationListComponent {
@Input() show: boolean = false;
@Input() showHeadline: string = '';
@Input() noShowHeadline: string = '';
@Input() relations: RelationResponse[] = [];
@Input() enableAccept: boolean = false;
@Input() enableBlock: boolean = false;
@Input() enableDelete: boolean = false;
...
}
Child - Show Friends - html
<div class="card p-3 mt-3">
<h5 class="card-title">{{ showHeadline }}</h5>
<ng-container *ngFor="let relation of relations">
{{relation.contactUsername }}
</ng-container>
</div>
There's a very strange design in your code which is worth refactoring. You're making some crazy subscriptions and trying to filter them using
Utilfunctions. And you don't care about unsubscribing. This means that your subscriptions are alive even after the component was destroyed and this could lead to some strange errors.Using a filter operator and async pipe you can achieve both things while simplifying the code and making it less error prone.
And then one small change in the parent HTML, assign the value to relations with
requested$Observable using theasyncpipe. This way you don't need to worry about manually unsubscribing (which you didn't do in your code)To explain what I meant with my question in the comments. You can take a slice of the store directly in the child component and then you won't need to pass the values up and down between children and parent. Same applies to the
invokeFindRequestedRelationsaction. It can be dispatched from the child directly.See what suits you better or try both approaches to get better understanding of it.