为什么我的 Angular 路由教程的后续代码显示空白页?
Why is my followup code of the Angular routing Tutorial showing a blank page?
我正在学习 https://angular.io/start/routing 上的 Angular 教程。然而,在某个步骤之后,我的浏览器显示了一个空白页面并给了我
Error: Can't resolve all parameters for ProductDetailsComponent: (?)
在控制台中。
我尝试了不同的浏览器(默认使用 Firefox),还评论/尝试代码以查看导致错误的确切行(private route: ActivateRoute
在产品的构造函数中-details.component.ts) .
还检查了拼写错误/我是否确实遗漏了教程中的某些内容,但据我所知,我已经按照它进行了 100%。
我还使用 Ubuntu Mate 19.04 和 IntelliJ IDEA。
产品-details.component.ts:
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { products } from '../products';
export class ProductDetailsComponent implements OnInit {
product;
constructor(
private route: ActivatedRoute,
) { }
}
ngOnInit() {
this.route.paramMap.subscribe(params => {
this.product = products[+params.get('productId')];
});
}
}
产品-details.component.html:
<h2>Product Details</h2>
<div *ngIf="product">
<h3>{{ product.name }}</h3>
<h4>{{ product.price | currency }}</h4>
<p>{{ product.description }}</p>
</div>
产品-list.component.ts:
import { Component } from '@angular/core';
import { products } from '../products';
@Component({
selector: 'app-product-list',
templateUrl: './product-list.component.html',
styleUrls: ['./product-list.component.css']
})
export class ProductListComponent {
products = products;
share() {
window.alert('The product has been shared!');
}
onNotify() {
window.alert('You will be notified when the product goes on sale');
}
}
产品-list.component.html:
<h2>Products</h2>
<div *ngFor="let product of products; index as productId">
<h3>
<a [title]="product.name + ' details'" [routerLink]="['/products', productId]">
{{ product.name }}
</a>
</h3>
<p *ngIf="product.description">
Description: {{ product.description }}
</p>
<button (click)="share()">
Share
</button>
<app-product-alerts
[product]="product"
(notify)="onNotify()">
</app-product-alerts>
</div>
app.module.ts:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouterModule, Routes } from '@angular/router';
import { ReactiveFormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { TopBarComponent } from './top-bar/top-bar.component';
import { ProductListComponent } from './product-list/product-list.component';
import { ProductAlertsComponent } from './product-alerts/product-alerts.component';
import { ProductDetailsComponent } from './product-details/product-details.component';
@NgModule({
imports: [
BrowserModule,
ReactiveFormsModule,
RouterModule.forRoot([
{ path: '', component: ProductListComponent },
{ path: 'products/:productId', component: ProductDetailsComponent },
])
],
declarations: [
AppComponent,
TopBarComponent,
ProductListComponent,
ProductAlertsComponent,
ProductDetailsComponent,
],
bootstrap: [ AppComponent ]
})
export class AppModule { }
products.ts:
export const products = [
{
name: 'Phone XL',
price: 799,
description: 'A large phone with one of the best screens'
},
{
name: 'Phone Mini',
price: 699,
description: 'A great phone with one of the best cameras'
},
{
name: 'Phone Standard',
price: 299,
description: ''
}
];
教程中预期的结果是路由将我从主视图重定向到特定产品的视图,但是在添加以上行之后,站点只显示一个空白页面。
从“../products”导入{产品};
您从哪里获得数据产品模型。
是否来自 REST API?
你能告诉我们你的 services.ts 和 product.ts 代码吗?
如果您正在从其他 API 获取产品数据。将该 Product 模型存储到 observable 中并在 ProductDetailsComponent 中订阅该产品模型。
如果您使用多项服务,请确保两项服务不相互依赖。
通过更新包依赖使其工作(参见https://github.com/lena-spb/untitled4):
package.json:
"dependencies": {
"rxjs": "6.5.2",
"tslib": "1.10.0",
"core-js": "2.6.9",
"zone.js": "0.9.1",
"jasmine-core": "2.99.1",
"@angular/core": "8.1.2",
"@angular/forms": "8.1.2",
"@angular/common": "8.1.2",
"@angular/router": "8.1.2",
"jasmine-marbles": "0.6.0",
"@angular/compiler": "8.1.2",
"web-animations-js": "2.3.2",
"@angular/animations": "8.1.2",
"@angular/platform-browser": "8.1.2",
"angular-in-memory-web-api": "0.8.0",
"@angular/platform-browser-dynamic": "8.1.2"
},
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
"devDependencies": {
"@angular-devkit/build-angular": "0.801.2",
"@angular/cli": "~8.1.2",
"@angular/compiler-cli": "~8.1.2",
"@angular/language-service": "~8.1.2",
"@types/node": "~8.9.4",
"@types/jasmine": "~2.8.8",
"@types/jasminewd2": "~2.0.3",
"codelyzer": "~4.5.0",
"jasmine-core": "~2.99.1",
"jasmine-spec-reporter": "~4.2.1",
"karma": "~3.0.0",
"karma-chrome-launcher": "~2.2.0",
"karma-coverage-istanbul-reporter": "~2.0.1",
"karma-jasmine": "~1.1.2",
"karma-jasmine-html-reporter": "^0.2.2",
"protractor": "~5.4.0",
"ts-node": "~8.3.0",
"tslint": "~5.11.0",
"typescript": "3.4.5"
}
src/app/app.module.ts:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import {RouterModule, Routes} from '@angular/router';
import { ReactiveFormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { TopBarComponent } from './top-bar/top-bar.component';
import { ProductListComponent } from './product-list/product-list.component';
import { ProductAlertsComponent } from './product-alerts/product-alerts.component';
import { ProductDetailesComponent } from './product-detailes/product-detailes.component';
const appRoutes: Routes = [
{ path: '', component: ProductListComponent },
{ path: 'products/:productId', component: ProductDetailesComponent }
];
@NgModule({
imports: [
BrowserModule,
ReactiveFormsModule,
RouterModule.forRoot(
appRoutes,
{ enableTracing: true } // <-- debugging purposes only
)
],
declarations: [
AppComponent,
TopBarComponent,
ProductListComponent,
ProductAlertsComponent,
ProductDetailesComponent
],
bootstrap: [ AppComponent ]
})
export class AppModule { }
src/app/product-detailes/product-detailes.component.ts:
import { Component, OnInit } from '@angular/core';
import {ActivatedRoute, ParamMap} from '@angular/router';
import { products } from '../products';
@Component({
selector: 'app-product-detailes',
templateUrl: './product-detailes.component.html',
styleUrls: ['./product-detailes.component.css']
})
export class ProductDetailesComponent implements OnInit {
product;
constructor(
private route: ActivatedRoute,
) { }
ngOnInit() {
this.route.paramMap.subscribe((params: ParamMap) => {
this.product = products[+params.get('productId')];
});
}
}
根据您的代码:ngOnInit()
方法写在 ProductDetailsComponent
之外,更新如下
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { products } from '../products';
export class ProductDetailsComponent implements OnInit {
product;
constructor(
private route: ActivatedRoute,
) { }
ngOnInit() {
this.route.paramMap.subscribe(params => {
this.product = products[+params.get('productId')];
});
}
}
product-details.component.ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { products } from '../products';
@Component({
selector: 'app-product-details',
templateUrl: './product-details.component.html',
styleUrls: ['./product-details.component.css']
})
export class ProductDetailsComponent implements OnInit {
product;
constructor(
private route: ActivatedRoute,
) { }
ngOnInit() {
this.route.paramMap.subscribe(params => {
this.product = products[+params.get('productId')];
});
}
}
product-list.component.ts
import { Component } from '@angular/core';
import { products } from '../products';
@Component({
selector: 'app-product-list',
templateUrl: './product-list.component.html',
styleUrls: ['./product-list.component.css']
})
export class ProductListComponent {
products = products;
share() {
window.alert('The product has been shared!');
}
onNotify() {
window.alert('You will be notified when the product goes on sale');
}
}
App.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { ProductDetailsComponent } from './product-details/product-details.component';
import { ProductListComponent } from './product-list/product-list.component';
@NgModule({
declarations: [
AppComponent,
ProductDetailsComponent,
ProductListComponent
],
imports: [
BrowserModule,
AppRoutingModule,
RouterModule.forRoot([
{ path: '', component: ProductListComponent },
{ path: 'products/:productId', component: ProductDetailsComponent },
])
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
成功了:
ngOnInit() {
this.route.paramMap.subscribe((params: ParamMap) => {
let productId = params.get('productId') || 0;
this.product = products[productId] || null;
});
}
我正在学习 https://angular.io/start/routing 上的 Angular 教程。然而,在某个步骤之后,我的浏览器显示了一个空白页面并给了我
Error: Can't resolve all parameters for ProductDetailsComponent: (?)
在控制台中。
我尝试了不同的浏览器(默认使用 Firefox),还评论/尝试代码以查看导致错误的确切行(private route: ActivateRoute
在产品的构造函数中-details.component.ts) .
还检查了拼写错误/我是否确实遗漏了教程中的某些内容,但据我所知,我已经按照它进行了 100%。
我还使用 Ubuntu Mate 19.04 和 IntelliJ IDEA。
产品-details.component.ts:
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { products } from '../products';
export class ProductDetailsComponent implements OnInit {
product;
constructor(
private route: ActivatedRoute,
) { }
}
ngOnInit() {
this.route.paramMap.subscribe(params => {
this.product = products[+params.get('productId')];
});
}
}
产品-details.component.html:
<h2>Product Details</h2>
<div *ngIf="product">
<h3>{{ product.name }}</h3>
<h4>{{ product.price | currency }}</h4>
<p>{{ product.description }}</p>
</div>
产品-list.component.ts:
import { Component } from '@angular/core';
import { products } from '../products';
@Component({
selector: 'app-product-list',
templateUrl: './product-list.component.html',
styleUrls: ['./product-list.component.css']
})
export class ProductListComponent {
products = products;
share() {
window.alert('The product has been shared!');
}
onNotify() {
window.alert('You will be notified when the product goes on sale');
}
}
产品-list.component.html:
<h2>Products</h2>
<div *ngFor="let product of products; index as productId">
<h3>
<a [title]="product.name + ' details'" [routerLink]="['/products', productId]">
{{ product.name }}
</a>
</h3>
<p *ngIf="product.description">
Description: {{ product.description }}
</p>
<button (click)="share()">
Share
</button>
<app-product-alerts
[product]="product"
(notify)="onNotify()">
</app-product-alerts>
</div>
app.module.ts:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouterModule, Routes } from '@angular/router';
import { ReactiveFormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { TopBarComponent } from './top-bar/top-bar.component';
import { ProductListComponent } from './product-list/product-list.component';
import { ProductAlertsComponent } from './product-alerts/product-alerts.component';
import { ProductDetailsComponent } from './product-details/product-details.component';
@NgModule({
imports: [
BrowserModule,
ReactiveFormsModule,
RouterModule.forRoot([
{ path: '', component: ProductListComponent },
{ path: 'products/:productId', component: ProductDetailsComponent },
])
],
declarations: [
AppComponent,
TopBarComponent,
ProductListComponent,
ProductAlertsComponent,
ProductDetailsComponent,
],
bootstrap: [ AppComponent ]
})
export class AppModule { }
products.ts:
export const products = [
{
name: 'Phone XL',
price: 799,
description: 'A large phone with one of the best screens'
},
{
name: 'Phone Mini',
price: 699,
description: 'A great phone with one of the best cameras'
},
{
name: 'Phone Standard',
price: 299,
description: ''
}
];
教程中预期的结果是路由将我从主视图重定向到特定产品的视图,但是在添加以上行之后,站点只显示一个空白页面。
从“../products”导入{产品};
您从哪里获得数据产品模型。 是否来自 REST API?
你能告诉我们你的 services.ts 和 product.ts 代码吗?
如果您正在从其他 API 获取产品数据。将该 Product 模型存储到 observable 中并在 ProductDetailsComponent 中订阅该产品模型。
如果您使用多项服务,请确保两项服务不相互依赖。
通过更新包依赖使其工作(参见https://github.com/lena-spb/untitled4):
package.json:
"dependencies": {
"rxjs": "6.5.2",
"tslib": "1.10.0",
"core-js": "2.6.9",
"zone.js": "0.9.1",
"jasmine-core": "2.99.1",
"@angular/core": "8.1.2",
"@angular/forms": "8.1.2",
"@angular/common": "8.1.2",
"@angular/router": "8.1.2",
"jasmine-marbles": "0.6.0",
"@angular/compiler": "8.1.2",
"web-animations-js": "2.3.2",
"@angular/animations": "8.1.2",
"@angular/platform-browser": "8.1.2",
"angular-in-memory-web-api": "0.8.0",
"@angular/platform-browser-dynamic": "8.1.2"
},
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
"devDependencies": {
"@angular-devkit/build-angular": "0.801.2",
"@angular/cli": "~8.1.2",
"@angular/compiler-cli": "~8.1.2",
"@angular/language-service": "~8.1.2",
"@types/node": "~8.9.4",
"@types/jasmine": "~2.8.8",
"@types/jasminewd2": "~2.0.3",
"codelyzer": "~4.5.0",
"jasmine-core": "~2.99.1",
"jasmine-spec-reporter": "~4.2.1",
"karma": "~3.0.0",
"karma-chrome-launcher": "~2.2.0",
"karma-coverage-istanbul-reporter": "~2.0.1",
"karma-jasmine": "~1.1.2",
"karma-jasmine-html-reporter": "^0.2.2",
"protractor": "~5.4.0",
"ts-node": "~8.3.0",
"tslint": "~5.11.0",
"typescript": "3.4.5"
}
src/app/app.module.ts:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import {RouterModule, Routes} from '@angular/router';
import { ReactiveFormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { TopBarComponent } from './top-bar/top-bar.component';
import { ProductListComponent } from './product-list/product-list.component';
import { ProductAlertsComponent } from './product-alerts/product-alerts.component';
import { ProductDetailesComponent } from './product-detailes/product-detailes.component';
const appRoutes: Routes = [
{ path: '', component: ProductListComponent },
{ path: 'products/:productId', component: ProductDetailesComponent }
];
@NgModule({
imports: [
BrowserModule,
ReactiveFormsModule,
RouterModule.forRoot(
appRoutes,
{ enableTracing: true } // <-- debugging purposes only
)
],
declarations: [
AppComponent,
TopBarComponent,
ProductListComponent,
ProductAlertsComponent,
ProductDetailesComponent
],
bootstrap: [ AppComponent ]
})
export class AppModule { }
src/app/product-detailes/product-detailes.component.ts:
import { Component, OnInit } from '@angular/core';
import {ActivatedRoute, ParamMap} from '@angular/router';
import { products } from '../products';
@Component({
selector: 'app-product-detailes',
templateUrl: './product-detailes.component.html',
styleUrls: ['./product-detailes.component.css']
})
export class ProductDetailesComponent implements OnInit {
product;
constructor(
private route: ActivatedRoute,
) { }
ngOnInit() {
this.route.paramMap.subscribe((params: ParamMap) => {
this.product = products[+params.get('productId')];
});
}
}
根据您的代码:ngOnInit()
方法写在 ProductDetailsComponent
之外,更新如下
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { products } from '../products';
export class ProductDetailsComponent implements OnInit {
product;
constructor(
private route: ActivatedRoute,
) { }
ngOnInit() {
this.route.paramMap.subscribe(params => {
this.product = products[+params.get('productId')];
});
}
}
product-details.component.ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { products } from '../products';
@Component({
selector: 'app-product-details',
templateUrl: './product-details.component.html',
styleUrls: ['./product-details.component.css']
})
export class ProductDetailsComponent implements OnInit {
product;
constructor(
private route: ActivatedRoute,
) { }
ngOnInit() {
this.route.paramMap.subscribe(params => {
this.product = products[+params.get('productId')];
});
}
}
product-list.component.ts
import { Component } from '@angular/core';
import { products } from '../products';
@Component({
selector: 'app-product-list',
templateUrl: './product-list.component.html',
styleUrls: ['./product-list.component.css']
})
export class ProductListComponent {
products = products;
share() {
window.alert('The product has been shared!');
}
onNotify() {
window.alert('You will be notified when the product goes on sale');
}
}
App.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { ProductDetailsComponent } from './product-details/product-details.component';
import { ProductListComponent } from './product-list/product-list.component';
@NgModule({
declarations: [
AppComponent,
ProductDetailsComponent,
ProductListComponent
],
imports: [
BrowserModule,
AppRoutingModule,
RouterModule.forRoot([
{ path: '', component: ProductListComponent },
{ path: 'products/:productId', component: ProductDetailsComponent },
])
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
成功了:
ngOnInit() {
this.route.paramMap.subscribe((params: ParamMap) => {
let productId = params.get('productId') || 0;
this.product = products[productId] || null;
});
}