如何在Angular中获取当前课程ID并通过props传入loadOneCourse方法?
Hey, let's tackle your two Angular/NgRx questions one by one—they're pretty common scenarios, so I'll break this down clearly for you:
There are three common ways to grab the current course ID, depending on where it's stored:
From Route Parameters (most common if it's in your URL)
If your route looks like/courses/:courseId, useActivatedRouteto pull the ID from the URL:import { ActivatedRoute } from '@angular/router'; import { takeUntil } from 'rxjs'; constructor(private route: ActivatedRoute) {} ngOnInit(): void { this.route.paramMap.pipe( takeUntil(this.destroySubject$), map(params => params.get('courseId')) // Gets the ID from the route ).subscribe(courseId => { if (courseId) { // Use the courseId here } }); }From NgRx Store (if it's already in your state)
Since you're usingselectCourseToBeEnrolled, you can either select the ID directly (if you have a dedicated selector) or extract it from the course object:// Option 1: Dedicated selector (cleaner if you have one) this._store.select(selectCurrentCourseId).pipe(takeUntil(this.destroySubject$)) .subscribe(courseId => { /* Use the ID */ }); // Option 2: Extract from the existing course selector this._store.select(selectCourseToBeEnrolled).pipe( takeUntil(this.destroySubject$), filter(course => !!course), map(course => course.id) ).subscribe(courseId => { /* Use the ID */ });From Component Input (if passed from a parent component)
If a parent component is passing the ID down, use an@Input()property:@Input() courseId: string; // Or number, depending on your ID type ngOnInit(): void { if (this.courseId) { // Use the courseId here } }
loadOneCourse in Your Code Your current code has a nested subscription (which we should avoid for cleaner RxJS) and needs to pass the course ID to loadOneCourse. Here's a revised version that fixes both issues:
import { EMPTY, switchMap } from 'rxjs'; ngOnInit(): void { this._store.select(AuthSelectors.isLoggedIn).pipe( takeUntil(this.destroySubject$), // Switch to the course selector only if user is logged in switchMap((isLoggedIn) => { if (!isLoggedIn) { return EMPTY; // Do nothing if user isn't logged in } // Get the course to enroll, filter out null/undefined, take only the first value return this._store.select(selectCourseToBeEnrolled).pipe( filter(value => !!value), first() ); }), // Now we have the valid course object—dispatch both actions tap((course) => { this._store.dispatch(enrollWhatToLearnCourse({ id: course.id, title: course.title, enroll: false })); // Pass the course ID to loadOneCourse here this._store.dispatch(loadOneCourse({ id: course.id })); }) ).subscribe(); }
Key Changes:
- Removed nested subscriptions: Used
switchMapto flatten the observable chain—this is a best practice in RxJS to avoid callback hell. - Guaranteed valid course data: The
filter(value => !!value)andfirst()ensure we only proceed when we have a valid course object with an ID. - Passed the ID directly: We extract
course.idfrom the selected course and pass it as theidproperty in theloadOneCourseaction props.
If your course ID comes from the route instead of the store, you can adjust the code to combine the route parameter stream with the logged-in state:
import { combineLatest } from 'rxjs'; ngOnInit(): void { combineLatest([ this._store.select(AuthSelectors.isLoggedIn).pipe(takeUntil(this.destroySubject$)), this.route.paramMap.pipe( takeUntil(this.destroySubject$), map(params => params.get('courseId')), filter(Boolean) // Ensure we have a valid ID ) ]).pipe( tap(([isLoggedIn, courseId]) => { if (isLoggedIn) { // If you need the course title for enrollWhatToLearnCourse, you might need to fetch it first or select it from store this._store.dispatch(enrollWhatToLearnCourse({ id: courseId, title: '', // Replace with actual title if needed enroll: false })); } this._store.dispatch(loadOneCourse({ id: courseId })); }) ).subscribe(); }
内容的提问来源于stack exchange,提问作者digitalboot

