Ale*_*iev 2 angular angular-router
我需要根据从 API(站点地图)接收的数据在 Angular 应用程序启动时创建路由。\n1. APP_INITIALIZER 调用 SettingsService.loadSettings 从 API 获取数据\n2。数据到达 ROUTES 并构建所需的路线。
\n\n应用程序模块.ts
\n\nimport { BrowserModule } from \'@angular/platform-browser\';\nimport { NgModule, APP_INITIALIZER } from \'@angular/core\';\nimport { HttpClientModule } from \'@angular/common/http\';\nimport { RouterModule, ROUTES } from \'@angular/router\';\n\nimport { AppComponent } from \'./app.component\';\nimport { MuseumComponent } from \'./museum/museum.component\';\nimport { SettingsService } from \'./services/settings.service\';\n\nexport function initSettings(settings: SettingsService) {\n return () => settings.loadSettings();\n}\n\nexport function buildRoutes(settings: SettingsService) {\n console.log(\'SettingsService.currentSettings\', settings.currentSettings);\n const routes = [];\n settings.currentSettings.site_map.forEach(element => {\n routes.push({\n path: `/${element.url}`,\n component: MuseumComponent\n });\n });\n routes.push({\n path: \'**\',\n component: AppComponent\n });\n console.log(routes);\n return routes;\n}\n\n@NgModule({\n declarations: [\n AppComponent,\n MuseumComponent\n ],\n imports: [\n BrowserModule,\n HttpClientModule,\n RouterModule.forRoot([])\n ],\n providers: [\n SettingsService,\n {\n \'provide\': APP_INITIALIZER,\n \'useFactory\': initSettings,\n \'deps\': [SettingsService],\n \'multi\': true\n },\n {\n \'provide\': ROUTES,\n \'multi\': true,\n \'useFactory\': buildRoutes,\n \'deps\': [SettingsService]},\n ],\n bootstrap: [AppComponent]\n})\nexport class AppModule { }\nRun Code Online (Sandbox Code Playgroud)\n\n设置.service.ts
\n\nimport { Injectable } from \'@angular/core\';\nimport { HttpClient, HttpHeaders } from \'@angular/common/http\';\n\nimport { Config } from \'./../config\';\n\n@Injectable()\nexport class SettingsService {\n\n private apiUrl = Config.apiUrl;\n\n public currentSettings;\n\n constructor(\n private http: HttpClient\n ) { }\n\n loadSettings(): Promise<any> {\n return new Promise ((resolve, reject) => {\n const url = this.apiUrl + `/settings`;\n this.http.get(url)\n .subscribe(\n response => {\n console.log(\'API answer: \', response);\n this.currentSettings = response;\n resolve(true);\n },\n err => {\n console.log(\'Server error: \' + JSON.stringify(err));\n reject(false);\n }\n );\n });\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n我在控制台上收到错误:
\n\nSettingsService.currentSettings undefined\nmain.ts:12 TypeError: Cannot read property \'site_map\' of undefined\nRun Code Online (Sandbox Code Playgroud)\n\n如果我这样做:
\n\n应用程序模块.ts
\n\nexport function buildRoutes(settings: SettingsService) {\n console.log(\'SettingsService.currentSettings\', settings.currentSettings);\n const routes = [];\n /*settings.currentSettings.site_map.forEach(element => {\n routes.push({\n path: `/${element.url}`,\n component: MuseumComponent\n });\n });*/\n routes.push({\n path: \'**\',\n component: AppComponent\n });\n console.log(routes);\n return routes;\n}\nRun Code Online (Sandbox Code Playgroud)\n\n我收到:
\n\nSettingsService.currentSettings undefined\napp.module.ts:27 [{\xe2\x80\xa6}]\n0: {path: "**", component: \xc6\x92} length: 1 __proto__: Array(0)\nsettings.service.ts:23 API answer: {languages: Array(2), entity_types: \nArray(5), site_map: Array(2)}\ncore.js:3688 Angular is running in the development mode. Call \nenableProdMode() to enable the production mode.\nRun Code Online (Sandbox Code Playgroud)\n\n看起来,ROUTES 发生在 APP_INITIALIZER 之前。为什么会这样?
\n我使用了错误的方法,解决方案是在这里建立的Angular。使用 APP_INITIALIZER 时路由器 DI 不工作
正确的代码:
应用程序模块.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule, APP_INITIALIZER } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { RouterModule } from '@angular/router';
import { AppComponent } from './app.component';
import { MuseumComponent } from './museum/museum.component';
import { SettingsService } from './services/settings.service';
import { ApiService } from './services/api.service';
export function initSettings(settings: SettingsService) {
return () => settings.loadSettings();
}
@NgModule({
declarations: [
AppComponent,
MuseumComponent
],
imports: [
BrowserModule,
HttpClientModule,
RouterModule.forRoot([])
],
entryComponents: [
MuseumComponent
],
providers: [
SettingsService,
ApiService,
{
'provide': APP_INITIALIZER,
'useFactory': initSettings,
'deps': [SettingsService],
'multi': true,
}
],
bootstrap: [AppComponent]
})
export class AppModule { }
Run Code Online (Sandbox Code Playgroud)
设置.service.ts
import { Injectable, Injector } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Router } from '@angular/router';
import { ApiService } from './api.service';
import { MuseumComponent } from '../museum/museum.component';
@Injectable()
export class SettingsService {
currentSettings: any;
constructor(
private injector: Injector,
private api: ApiService
) { }
loadSettings(): Promise<any> {
return new Promise((resolve, reject) => {
setTimeout(() => {
const router = this.injector.get(Router);
console.log(router);
this.api.getSettings()
.subscribe(
response => {
this.currentSettings = response;
this.currentSettings.site_map.forEach(element => {
router.config.push({ path: `${element.url}`, component: MuseumComponent });
});
resolve(true);
},
err => {
console.log(err);
reject(false);
}
);
});
});
}
}
Run Code Online (Sandbox Code Playgroud)
api.service.ts
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { Config } from './../config';
@Injectable()
export class ApiService {
private apiUrl = Config.apiUrl;
constructor(
private http: HttpClient
) { }
public getSettings(): Observable<any> {
const url = this.apiUrl + `/settings`;
return this.http.get(url);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4910 次 |
| 最近记录: |