Angular 6 在两个不相关的组件之间传递数据

标签 angular typescript routing observable

我有包含来 self 的后端应用程序的数据(命名类(class))的类(class)详细信息组件,我想将该数据传递给与该组件无关的另一个组件(类(class)播放)。我想在这两个组件中显示从后端获得的相同数据。这是相关文件:

应用路由模块:

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 {  }

类(class)/类(class)(界面)

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;
}

类(class)/类(class).服务:

import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';

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{
  constructor(private http: HttpClient) {  }

  private url = 'http://localhost:3000/courses';
  private courseUrl = 'http://localhost:3000/courses.json';

  // 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));
  }


}

类(class)/类(class)详情/类(class)详情.ts:

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);
   }

   onBack(): void {
     this.router.navigate(['/courses']);
   }

}

类(class)/类(class)播放/类(class)播放.ts:

import { Component, OnInit} from '@angular/core';
import { ActivatedRoute, Router, Routes, NavigationEnd } from '@angular/router';
import { MatSidenavModule } from '@angular/material/sidenav';

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 {
  courseId: number;
  errorMessage: string;
  private sub: any;

  constructor(private courseService: CourseService,
      private route: ActivatedRoute,
      private router: Router) {

    }

    ngOnInit() {


      }


     onBack(): void {
       this.router.navigate(['/courses/:id']);
     }

}

最佳答案

在不引入任何其他库的情况下,Angular 指定了几种组件相互通信的方式。 Documentation

由于您的组件不是父/子组件而是兄弟组件,因此选择更加有限。

  1. 让共享父组件将数据传递给两个子组件
  2. 将数据存储在共享服务中

根据您展示的代码,我相信#2 是您的最佳选择。因此,您可以向 CourseService 添加一个属性:

public selectedCourse: ICourse;

然后你可以在两个组件中访问它:

this.courseService.selectedCourse;

这种方法的问题是你必须管理一个伪全局状态并确保服务只被注入(inject)/提供一次(否则每个组件将获得它自己的服务实例并且你不能共享数据)。


正如 Pavan 在对问题的评论中指出的那样,您可能应该使用 Observable 并订阅它。使用上述方法,组件将不会在值更改时收到通知,并且需要主动检查负载变化。

关于Angular 6 在两个不相关的组件之间传递数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51423868/

相关文章:

routing - 启用推送状态和上下文路径路由 : Static assets are not found on the server

Angular2设计——组件嵌套和性能风险

javascript - 无法将数据从应用程序组件传递到函数

angular - 路由到 router-outlet 内的组件

angular - Ionic 4每次进入都会刷新标签页

node.js - 根据环境使用不同的 ormconfig.json 文件

node.js - Mongoose 错误: Property 'Buffer' does not exist on type 'typeof globalThis'

c# - 如何通过 ASP.NET 重定向和修改无扩展名的 URL?

javascript - 如何快速修复 VS 代码中的所有内容( typescript )

ruby-on-rails - Rails:重定向到当前路径,但不同的子域