Угловой 7 маршрут по клику после полного выполнения http-запроса - PullRequest
0 голосов
/ 22 декабря 2018

У меня есть Список записей, и когда я нажимаю на один список, я попадаю в более подробный вид элемента.Теперь это представление загружается через http-запрос (который занимает немного больше времени, чем маршрутизация от страницы к странице).Допустим, у меня есть следующий код:

Для страницы назначения:

 projectNumber: string = '';

  ngOnInit() {
  }

  constructor(
    private router: Router,
    private route: ActivatedRoute,
    private logger: LoggerService,
    private projectReceiverService: ProjectReceiverService
  ) {
    this.initProjectDataFromProjectNumber(this.route.snapshot.paramMap.get('projectNum'));
  }

  initProjectDataFromProjectNumber(projectNumber: string) {
    let project = this.projectReceiverService.getProjectByNumber(projectNumber); 
    this.projectNumber = projectNumber; //getProjectNumber => results in error
  }

Для услуги:

 getProjectByNumber(projectNumber: string): Project {
 let project: Project; 
 this.http.get(httpBaseUrl + "/project/getProject/" + projectNumber, httpOptions).subscribe((data) => {
  this.logger.info("Received data, processing...");
  project = data['projectDto'];
},
(error) => {
  this.logger.error("Error when receiving project.");
  this.logger.error(error.message);
});;
 return project;
}

И для предыдущей страницы (гдеЯ щелкаю по пункту):

 projectClicked(projectNumber: string) {
    this.routeTo('projects/' + projectNumber);
  }

Теперь было бы замечательно, если бы я мог каким-то образом управлять маршрутизацией после того, как http-запрос был полностью выполнен (поскольку я мог, например, передать объект проекта непосредственно при маршрутизации итакже я бы не стал бороться с отображением некоторых данных, которые еще не загружены на странице с подробной информацией).Как я мог это сделать?Я думал о загрузке на предыдущую сторону до того, как что-то щелкнет, но это было бы адской перегрузкой, чтобы предварительно загрузить все детали для каждого элемента.

1 Ответ

0 голосов
/ 22 декабря 2018

Вы можете сделать это относительно легко с помощью распознавателя маршрутов.

Это так.В вашей конфигурации маршрута вы указываете свой маршрут, компонент и resolver.

const routes = [{
  path: 'projects/:projectNumber',
  component: DestinationComponent,
  resolve: {
    project: ProjectResolver
  },
}];

Теперь вам нужно поместить этот маршрут в модуль, а предоставить упомянутый вами преобразователь * 1008.*.Например, вот так:

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule],
  providers: [ProjectResolver],
})
export class ProjectDetailsModule {}

Но что это за ProjectResolver?Это просто инъецируемый класс, реализующий интерфейс Resolve Angular, который в своем методе resolve() возвращает данные в виде данных, Promise или Observable.Выглядит это так:

import { Injectable } from '@angular/core';
import { Resolve } from '@angular/router';
// You will also need your service
import { ProjectService } from './project.service';

@Injectable()
export class ProjectResolver implements Resolve {
  // Inject it with where the data comes from
  constructor(private projectService: ProjectService) {}

  // Now implement the resolve interface. Angular will give you the route,
  // from which you can read the parameter.
  resolve(route: ActivatedRouteSnapshot): Observable<Project> {
    const projectNumber = route.snapshot.params['projectNumber'];
    return this.projectService.getProjectByNumber(projectNumber);
  }
}

Теперь нам нужно немного исправить вашу службу - метод http обычно асинхронный, поэтому вы должны вместо этого вернуть наблюдаемое:

// I'll change the return type, from Project, to Obsevable<Project>
getProjectByNumber(projectNumber: string): Observable<Project> {
  return this.http.get(`${ httpBaseUrl }/project/getProject/${ projectNumber }`,  httpOptions)
    // Instead of subscribe, you'll use a pipe, to map. So that others can actually subscribe (in our case the Angular router)
    .pipe(
      map(data => {
        this.logger.info("Received data, processing...");
        project = data['projectDto'];
        return project;

        // This whole `map(...)` part could have been a one-liner:
        // map(data => data.projectDto)
        // so alltogether:
        // this.http.get().pipe( map(data => data.projectDto), catchError(this.logger.error));
    },
    catchError(err => this.logger.error('Error getting project:', err.message)),
  );
}

Толькоосталось одно.Как мы получаем данные один раз в компоненте?С маршрута снова.

// in the component
ngOnInit() {
  this.activatedRoute.data.subscribe(project => this.project = project);
  // or something like this for immediate value:
  // this.data = this.route.snapshot.data;
}

Обратите внимание, что это будет держать вашу страницу в «загрузке», пока данные не вернутся.Если вы хотите получать данные параллельно, это другой ответ, но это также может быть сделано.

...