我有一个课程详细信息组件,其中包含来自后端应用程序的数据(名为课程),我想将该数据传递给与该组件无关的另一个组件(课程播放)。我想在这两个组件中显示从后端获取的相同数据。另外,在课程播放中,我想使用html文件中的当前ID,以便可以从中获取数据,但我不知道如何。我没有收到任何错误消息,但是课程播放没有显示任何内容。 这些是相关文件:
app-routing-module:
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { CourseListComponent } from './courses/course-list/course-list.component';
import { CourseDetailComponent } from './courses/course-detail/course-detail.component';
import { CoursePlayComponent } from './courses/course-play/course-play.component';
import { PageNotFoundComponent } from './page-not-found/page-not-found.component';
const appRoutes: Routes = [
{ path: '', redirectTo: '/courses', pathMatch: 'full' },
{ path: 'courses', component: CourseListComponent, pathMatch: 'full' },
{ path: 'courses/:id', component: CourseDetailComponent, pathMatch: 'full'},
{ path: 'courses/:id/:id', component: CoursePlayComponent, pathMatch: 'full' },
{ path: '**', component: PageNotFoundComponent, pathMatch: 'full' }];
@NgModule({
imports: [RouterModule.forRoot(appRoutes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
课程/课程(界面)
export interface ICourse {
course_id: number;
title: string;
autor: string;
segments: ISegment[];
}
export interface ISegment {
segment_id: number;
unit_id: number;
unit_title: string;
name: string;
type: string;
data: string;
}
courses / course.service:
import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Subject } from 'rxjs';
import { Observable, throwError } from 'rxjs';
import { catchError, groupBy } from 'rxjs/operators';
import { ICourse } from './course';
// Inject Data from Rails app to Angular app
@Injectable()
export class CourseService{
private url = 'http://localhost:3000/courses';
private courseUrl = 'http://localhost:3000/courses.json';
private courseSub: Subject<ICourse> = new Subject();
private course$: Observable<ICourse> = this.courseSub.asObservable();
constructor(private http: HttpClient) { }
public send(value) {
this.courseSub.next(value);
}
// Handle Any Kind of Errors
private handleError(error: HttpErrorResponse) {
// A client-side or network error occured. Handle it accordingly.
if (error.error instanceof ErrorEvent) {
console.error('An error occured:', error.error.message);
}
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong.
else {
console.error(
'Backend returned code ${error.status}, ' +
'body was ${error.error}');
}
// return an Observable with a user-facing error error message
return throwError(
'Something bad happend; please try again later.');
}
// Get All Courses from Rails API App
getCourses(): Observable<ICourse[]> {
const coursesUrl = `${this.url}` + '.json';
return this.http.get<ICourse[]>(coursesUrl)
.pipe(catchError(this.handleError));
}
// Get Single Course by id. will 404 if id not found
getCourse(id: number): Observable<ICourse> {
const detailUrl = `${this.url}/${id}` + '.json';
return this.http.get<ICourse>(detailUrl)
.pipe(catchError(this.handleError));
}
}
courses / course-detail.component:
import { Component, OnInit, Pipe, PipeTransform } from '@angular/core';
import { ActivatedRoute, Router, Routes } from '@angular/router';
import { ICourse } from '../course';
import { CourseService } from '../course.service';
@Component({
selector: 'lg-course-detail',
templateUrl: './course-detail.component.html',
styleUrls: ['./course-detail.component.sass']
})
export class CourseDetailComponent implements OnInit {
course: ICourse;
errorMessage: string;
constructor(private courseService: CourseService,
private route: ActivatedRoute,
private router: Router) {
}
ngOnInit() {
const id = +this.route.snapshot.paramMap.get('id');
this.getCourse(id);
}
// Get course detail by id
getCourse(id: number) {
this.courseService.getCourse(id).subscribe(
course => this.course = course,
error => this.errorMessage = <any>error);
}
// Pass course to CoursePlayComponent
passData() {
this.courseService.send(course);
}
onBack(): void {
this.router.navigate(['/courses']);
}
}
courses / course-detail / course-detail.html:
<div id="main" class='course_detail' *ngIf="course">
<div class="row" id="course_detail_image">
<div class="col-lg-8">
<br>
<img src="./assets/images/lg-white.png" class="d-inline-block align-top" alt="">
</div>
</div>
<div class="row" id="course_detail_header">
<div class="container text-center">
<br>
<h1>{{course.title}}</h1>
<br>
</div>
</div>
<div class="row justify-content-lg-center" id="progress">
<div class="container text-center">
<div class="progress">
<div class="progress-bar bg-white"></div>
</div>
<td>Your Progress</td>
<br><br><br>
</div>
</div>
<div class="row" id="course_detail">
<div class="container">
<br>
<ul class="nav nav-tabs" role="tablist">
<li class="nav-item">
<a class="nav-link active" href="#Curiculum" role="tab" data-toggle="tab">Curiculum</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#About" role="tab" data-toggle="tab">About this course</a>
</li>
</ul>
<br>
<!-- Tab panes -->
<div class="tab-content">
<div role="tabpanel" class="tab-pane fade in active" id="Curiculum">
<h4>Course Overview</h4>
<ul *ngFor="let segment of course.segments">
<ul>
<li id="course_detail_title">Unit {{segment.unit_id}}: {{segment.unit_title}}</li>
<a class="course_detail_item" routerLink="/courses/{{course.id}}/{{segment.id}}" (click)="passData()" ><li>{{segment.name}}</li></a>
</ul>
</ul>
</div>
<div role="tabpanel" class="tab-pane fade" id="About">
<h4>Course Topics:</h4>
<td> text </td>
<br><br>
<h4>Course Expectations:</h4>
<td></td>
</div>
</div>
<br>
</div>
</div>
</div>
<router-outlet></router-outlet>
courses / course-play / course-play.component:
import { Component, OnInit, Input} from '@angular/core';
import { ActivatedRoute, Router, Routes, NavigationEnd } from '@angular/router';
import { MatSidenavModule } from '@angular/material/sidenav';
import { Subscription } from 'rxjs/Subscription';
import { ICourse } from '../course';
import { CourseService } from '../course.service';
@Component({
selector: 'lg-course-play-course-play',
templateUrl: './course-play.component.html',
styleUrls: ['./course-play.component.sass']
})
export class CoursePlayComponent implements OnInit {
errorMessage: string;
course: ICourse;
private sub: Subscription;
constructor(private courseService: CourseService,
private route: ActivatedRoute,
private router: Router) {
this.sub = courseService.course$.subscribe(
val => {val = this.course}
)}
ngOnInit() {
// get the current segment id to use it on the html file
const id = +this.route.snapshot.paramMap.get('id');
}
onBack(): void {
this.router.navigate(['/courses/:id']);
}
}
courses / course-play / course-play.html:
<div class="container-fluid" *ngIf='course'>
<div class="sidenav">
<div class="sidebar" id="header">
<br>
<img src="./assets/images/lg-white.png" class="d-inline-block align-top" alt="">
<br><br><br>
<h4 class="text-center"> {{course.title}} </h4>
</div>
<br>
<div *ngFor='let segment of course.segments'>
<td> Unit {{segment.unit_id}}: {{segment.unit_title}} </td>
<a href="#about">{{segment.name}}</a>
<br>
</div>
</div>
<div class="container-fulid text-center" id="body">
<br><br>
<h1>Current segment</h1>
<p> here show the info for the segment i get with id snapshot </p>
</div>
</div>
答案 0 :(得分:0)
如果要在不相关的组件之间共享数据,可以使用状态管理,例如 ngrx或Shared Service。
对于共享服务,请将其导入获取数据的组件中,因此course-detail
然后将数据传递给更新主题的服务。任何其他需要数据的组件(例如course-play
)都可以订阅它。