Angular 6将数据从组件传递到不相关的组件 [英] Angular 6 Pass data from component to unrelated one

查看:68
本文介绍了Angular 6将数据从组件传递到不相关的组件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个课程详细信息组件,其中包含来自后端应用程序的数据(名为课程),我想将该数据传递给与该组件无关的另一个组件(课程播放)。我想在这两个组件中显示从后端获取的相同数据。另外,在课程播放中,我想使用html文件中的当前ID,以便可以从中获取数据,但我不知道如何。我没有收到任何错误消息,但是在课程播放中什么也没有显示。
这是相关文件:

I have course-detail component that contain data (named course) from my backend app and I want to pass that data to another component (course-play) that's not related to the component. I want to display the same data I got from my backend in this two components. Also, in course-play I want to use the current id in the html file so I can get the data from it but I don't know how. I don't get any error message but course-play doesn't display anything. This are the relevant files:

应用程序路由模块:

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:

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:

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 :

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 :

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>

推荐答案

如果要在不相关的组件之间共享数据,可以使用状态管理,例如
ngrx 共享服务

If you want to share data between unrelated components you can use State Management like ngrx or a Shared Service.

对于共享服务,您将其导入获取数据的组件中,因此课程详细信息然后将数据传递给更新主题的服务。任何其他需要数据的组件(例如比赛过程)都可以订阅它。

For a shared service, you import it into the component where you get the data, so course-detail then pass the data to the service that updates the subject. Any other component that wants the data such as course-play just subscribes to it.

这篇关于Angular 6将数据从组件传递到不相关的组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆