I'm new to RxJs
operators and Observables
in general and was not sure how to get this simple code to work.
I have created a component called 'family-list
' that is bound to an observable of 'PlanMember[]
'. This is passed in from a container component.
Inside of this component, I want to be able to filter out the plan members so that we leave out the member with userType
'Owner
'. The code i have now fails because 'planMembers
' is undefined.
Please help!
@Component({
selector: 'pv-family-list',
templateUrl: './family-list.component.html',
styleUrls: ['./family-list.component.scss']
})
export class FamilyListComponent{
@Input() planMembers: Observable<PlanMember[]>;
@Output() remove: EventEmitter<string> = new EventEmitter<string>();
columnsToDisplay = ['name', 'email', 'status', 'cycleEnd', 'actions'];
constructor() {
this.planMembers.pipe(map( (members) => members.filter(m => m.userId !== 'Owner') )).subscribe();
}
removeUser (userId : string) {
this.remove.emit(userId);
}
}
EDIT: After using ngOnit to filter -- My page will load the component, but still getting errors. I'm also not even getting the member-list to filter properly -- still have all the members
So I have a "Subscription.container" component that holds this family-list component. I retrieve the list of family members from the store. this.familyPlanMembers$ = store.select(fromAccount.getPlanMembers);
Then, i bind my family-list planMembers with an Async Pipe: <pv-family-list (remove)="cancelMemberSubscription($event)" [planMembers]="(familyPlanMembers$ | async)" > </pv-family-list>
While the family-list loads, I'm getting this: TypeError: "this.planMembers is null"
Component Now:
@Component({
selector: 'pv-family-list',
templateUrl: './family-list.component.html',
styleUrls: ['./family-list.component.scss']
})
export class FamilyListComponent implements OnChanges{
@Input() planMembers: PlanMember[];
@Output() remove: EventEmitter<string> = new EventEmitter<string>();
columnsToDisplay = ['name', 'email', 'status', 'cycleEnd', 'actions'];
ngOnChanges() {
this.planMembers = this.planMembers.filter(m => m.userType !== 'Owner');
}
removeUser (userId : string) {
this.remove.emit(userId);
}
答案 0 :(得分:0)
It is undefined because it is not initialized. You should do filtering in ngOnInit and ngOnChanges hook or use set method
_planMembers: Observable<PlanMember[]>;
@Input
set planMembers(planMembers: Observable<PlanMember[]]) {
this._planMembers = planMembers;
this._planMembers
.pipe(map( (members) => members.filter(m => m.userId !== 'Owner')
)).subscribe();
}
This will be invoked every time when planMembers input would change.
答案 1 :(得分:0)
At constructor
time, your @Input
is not defined yet.
Move your code in ngOnInit
:
@Component({
selector: 'pv-family-list',
templateUrl: './family-list.component.html',
styleUrls: ['./family-list.component.scss']
})
export class FamilyListComponent implements OnInit{
@Input() planMembers: Observable<PlanMember[]>;
@Output() remove: EventEmitter<string> = new EventEmitter<string>();
columnsToDisplay = ['name', 'email', 'status', 'cycleEnd', 'actions'];
ngOnInit() {
this.planMembers.pipe(map( (members) => members.filter(m => m.userId !== 'Owner') )).subscribe();
}
removeUser (userId : string) {
this.remove.emit(userId);
}
}
Then it also depends how do you pass this input through this component, and how do you fetch the data, otherwise you should implement ngOnChanges
rather than ngOnInit
, or use a set
on the @Input
or a lot of other approaches are also possible
答案 2 :(得分:0)
Like the other answers already mentioned, the Observable isn't yet defined in the constructor. A constructor should only be used for DI or assignments imho.
I would suggest not to pass the observable as an input to your child components but to pass it as "just" an array. This will make your application faster, easier to work with and easier to test. To pass it as an array, use the async
pipe.
<pv-family-list [planMembers]="planMembers$ | async"><pv-family-list/>