【问题标题】:Angular 6 display data with HttpClient, RxJS and GroupByAngular 6 使用 HttpClient、RxJS 和 GroupBy 显示数据
【发布时间】:2018-07-09 11:01:45
【问题描述】:

我在后端使用 Ruby on Rails API 应用程序,在前端使用 Angular 6。这是我从后端得到的 json 响应:

loclhost3000/courses.json

[  
   {  
      id:1,
      title:"Introduction",
      author:"Dana Inbar",
      segments:[  

      ]
   },
   {  
      id:2,
      title:"Master the ELN",
      author:"Dana Inbar",
      segments:[  

      ]
   },
   {  
      id:3,
      title:"Master the Inventory",
      author:"Dana Inbar",
      segments:[  
         {  
            id:1,
            unit_id:1,
            unit_title:"Introduction",
            name:"Lesson 1: Introduction to the inventory module-                                       looking at one collection",
            data:"www.video01.com/vid.avi"
         },
         {  
            id:2,
            unit_id:2,
            unit_title:"Inventory Customisation",
            name:"Lesson 2: Setting up custom collections",
            data:"www.video02.com/vid.avi"
         },
         {  
            id:3,
            unit_id:2,
            unit_title:"Inventory Customisation",
            name:"Lesson 3: Adding a custom field",
            data:"www.video03.com/vid.avi"
         },
         {  
            id:4,
            unit_id:2,
            unit_title:"Inventory Customisation",
            name:"Lesson 4: Creating derived collections",
            data:"www.video04.com/vid.avi"
         },
         {  
            id:5,
            unit_id:2,
            unit_title:"Inventory Customisation",
            name:"Lesson 5: Using repositories",
            data:"www.video05.com/vid.avi"
         },
         {  
            id:6,
            unit_id:2,
            unit_title:"Inventory Customisation",
            name:"Quiz",
            data:"'[ { "            
              question 1":"___",
              "answers":{  
                "1":"____",
                "2":"____",
                "3":"____"
              },
              "correct_answer":"2"
            },
            {  
             "question 2":"___",
               "answers":{  
                "1":"____",
                "2":"____"
             },
              "correct_answer":"1"
             }
            }
           ] ' " 
         }
      ]
    }
]

我的课程模型有很多段,段是视频或测验。 我有课程列表、课程详细信息和课程播放组件。 我对课程详细信息有疑问,我希望课程详细信息页面如下所示:course-detail image

我认为我可以在 course.service 中使用 groupBy 与 unit_id 和 unit_title 并执行两个 ngFor(或 ngFor 组)的功能,但因为我是 Angular 新手,我不知道如何最好地实现这一点。

我正在从程序中添加一些可以提供帮助的文件:

./courses/course.module

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule, Routes } from '@angular/router';
import { MatSidenavModule } from '@angular/material/sidenav';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

import { CourseListComponent } from './course-list/course-list.component';
import { CourseDetailComponent } from './course-detail/course-detail.component';
import { CourseService } from './course.service';
import { CoursePlayComponent } from './course-play/course-play.component';

const coursesRoutes: Routes = [
  { path: 'courses', component: CourseListComponent },
  { path: 'courses/:id', component: CourseDetailComponent },
  { path: 'courses/:id/:segment_id', component: CoursePlayComponent }
]

@NgModule({
  imports: [
    CommonModule,
    MatSidenavModule,
    BrowserAnimationsModule,
    RouterModule.forChild(
      coursesRoutes
    )
  ],
  declarations: [
    CourseListComponent,
    CourseDetailComponent,
    CoursePlayComponent
  ],
  providers: [
    CourseService
  ]
})
export class CourseModule { }

./courses/course

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 } from '@angular/common/http';

import { Observable, throwError } from 'rxjs';
import { map, catchError, retry, groupBy, Filter } from 'rxjs/operators';

import { Course } 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)
        );

  }
}

./courses/course-detail/course-detail.component

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';

import { Course } 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']);
   }

}

./courses/course-detail/course-detail.html

<div id="main" *ngIf="course">
  <div class="row" id="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="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="body">
      <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">
            <h1>Course Overview</h1>
            <br>
            <ul *ngFor="let segment of course.segmentsByUnitId">
              <ul>
                <li id="title">Unit {{segment.unit_id}}: {{segment.unit_title}}</li>
                <li>{{segment.name}}</li>
              </ul>
            </ul>
          </div>

          <div role="tabpanel" class="tab-pane fade" id="About">
            <h1>Course Topics:</h1>
          </div>
        </div>
        <br>
      </div>
    </div>
</div>

./courses/course-detail/course-detail.sass

$color: #FFFFFF
$bg-col:  #5c0099
$prog-size: 10px

#image
  background-color: $bg-col
  color: $color

#header
  background-color: $bg-col
  color: $color

#body
  background-color: $color
  height: 100vh
  max-width: initial
  display: flex

#title
  font-weight: bold

#progress
  background-color: $bg-col
  color: $color
  font-size: $prog-size

.progress
    height: 10px
    left: 30%

.progress-bar
  width: 10%
  height: 20px
  background-color: transparent

【问题讨论】:

    标签: json angular group-by rxjs httpclient


    【解决方案1】:

    您可以使用下面的 groupby 管道来做到这一点。 GroupBy 管道返回一个键/值对的对象。 https://github.com/danrevah/ngx-pipes#groupby

    ngx-pipes的安装过程:https://github.com/danrevah/ngx-pipes#installation

    以下是我为我的数据实现它的方式: 我的数据:

    tsks = [{
          CompletedFlag: true,
          ProgressFlag: false,
          DueDate:"2014-10-02T13:12:37.027",
          Signup: "2014-10-04T11:51:10.137",
          ObMilestone: 1,
          ObTask: 119,
          AssignedToId: 0,
          Company: "ABC Corp",
          Description: "Lorem Ipsum",
          Favourite: null,
          FirstName: "Libin",
          LastName: "J",
          MilestoneName: "Blue",
          OnboarderStatus: "Live",
          Partner : null
        },
        {
         CompletedFlag: true,
          ProgressFlag: false,
          DueDate:"2014-10-02T13:12:37.027",
          Signup: "2014-10-04T11:51:10.137",
          ObMilestone: 1,
          ObTask: 119,
          AssignedToId: 0,
          Company: "ABC Corp",
          Description: "Lorem Ipsum",
          Favourite: null,
          FirstName: "Libin",
          LastName: "J",
          MilestoneName: "Blue",
          OnboarderStatus: "Live",
          Partner : null
        }];
    

    我的代码按“里程碑名称”分组

    <div class="row" *ngFor="let task of tsks | groupBy: 'MilestoneName' | pairs">
      <div>Group milestone name: {{task[0]}}</div>
    
      <div class="row" *ngFor="let t of task[1]">
        <div>Task: {{t.FirstName}}</div>
      </div>
    </div>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-17
      • 1970-01-01
      • 2019-04-24
      • 2021-05-06
      • 1970-01-01
      相关资源
      最近更新 更多