Router Resolver not rendering component

2019-06-28 08:22发布

问题:

I have this router resolver to retrieve data from the Google Firestore. I am trying to use the Resolver to fetch the data ahead. When I place debugger at resolve function it shows me the data retrieved from the Server. But it is never returning from the resolve() method. Can anyone please help me out.

Routing Module

const routes: Routes = [
    { path: '', component: HomeComponent},
    { path: 'projects', component: ProjectsComponent, resolve: {projectData: ProjectResolver} },
    { path: 'about', component: AboutComponent}
];

App Module

  providers: [
    ProjectService,
    ProjectResolver
  ],

Resolver Service

import { Observable } from 'rxjs';
import { ActivatedRouteSnapshot, RouterStateSnapshot, Resolve } from '@angular/router';
import { Injectable } from '@angular/core';
import { ProjectService } from './project.service';
import { map } from "rxjs/operators";
import { Project } from './project.model';

@Injectable()
export class ProjectResolver implements Resolve<Project[]> {

    constructor(private projectService: ProjectService ) {

    }

    resolve(route: ActivatedRouteSnapshot, router: RouterStateSnapshot) : Observable<Project[]> | any{
        return this.projectService.getProjects().pipe(map(project => {
            return project //Debugger shows fetched data(Array of projects)
        }
        ));
    }
}

Project Service

import { AngularFirestore } from 'angularfire2/firestore';
import { Observable } from "rxjs";
import { Injectable } from "@angular/core";

@Injectable()
export class ProjectService {

    constructor(private db: AngularFirestore) {}

    getProjects(): Observable<any> {
        return this.db.collection('currentProjects').valueChanges();
    }

}

** Project Component (This component in never loaded by Resolver )**

import { Component, OnInit, Injectable } from '@angular/core';
import { Project } from './project.model';
import { ActivatedRoute } from '@angular/router';
import { ProjectService } from './project.service';
import { Observable } from 'rxjs';

@Component({
  selector: 'app-projects',
  templateUrl: './projects.component.html',
  styleUrls: ['./projects.component.css']
})

export class ProjectsComponent implements OnInit {

   projects: Project[] = [];

  constructor(private route: ActivatedRoute, private projectService: ProjectService) { 
  }

  ngOnInit() {
      this.route.data.subscribe((data: Project[]) => {
        this.projects = data['projectData'];
      })
  }

}

回答1:

The problem is that the Angular Firebase Observable(event stream) will never complete like normal "observable" so it is never resolving. I modified the Observable with the "take" operator to get the first item and forced to complete.

this.db.collection('currentProjects').valueChanges().take(1);

Changes:

  • Removed ProjectService
  • Modified ProjectResolver
  • Modified ProjectComponent

I posted the solution to my problem below:

Project Resolver (Working)

export class ProjectResolver implements Resolve<any> {

    constructor(private db: AngularFirestore) {

    }

    resolve(route: ActivatedRouteSnapshot, router: RouterStateSnapshot) : any{

        return Observable.from(this.db.collection('currentProjects').valueChanges()
            .do(data => {  
                return data
            }).take(1))
    }
}

Project Component(Working)

export class ProjectsComponent implements OnInit {

  private projects: Project[];

  constructor(private route: ActivatedRoute) {

  }

  ngOnInit() {
    this.route.data.subscribe((data) => {
      this.projects = data['projectData'];
    })
  }
}


回答2:

Fetch data like this.route.snapshot.data instead of this.route.data and no need to subscribe to it

ngOnInit() {          
   this.projects = this.route.snapshot.data['projectData'];
}