【发布时间】:2026-02-22 17:00:01
【问题描述】:
我是 Angular 2 的初学者,我正在构建我的第一个应用程序,同时遵循 Pluralsight 课程。 我正在使用打字稿。 我有一个特定的组件(名为:property-detail.component.ts),我试图在其中引用来自服务(property.service.ts)的指令。 我在根模块中注册服务,并使用“contructor”方法将服务注入到组件中。 在一个组件(property-list.component.ts)中,我调用了一个产品列表,这很好用。 然后我尝试在(property-detail.component.ts)中调用相同的服务,我只想显示单个属性的详细信息,但是当我运行应用程序时,出现以下错误
错误信息
{node_modules/@angular/core/bundles/core.umd.js:3462 EXCEPTION: Uncaught (in promise): Error: Error in app/property/property-detail.component.html:9:42 caused by: Cannot read property 'propertyName' of undefined
TypeError: Cannot read property 'propertyName' of undefined
at _View_PropertyDetailComponent0.detectChangesInternal (PropertyDetailComponent.ngfactory.js:284:62)}
我正在为整个应用程序使用单个应用程序模块 (app.module.ts),以便为自己简化它。
这里是组件和模块:
app.module.ts
import { NgModule } from '@angular/core';
//brownermodule exposes the ngIg and ngFor directive
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { RouterModule } from '@angular/router';
import { AppComponent } from './app.component';
import { PropertyListComponent } from "./property/property-list.component";
import { PropertyCityFilterPipe } from "./property/property-cityfilter.pipe";
import { StarComponent } from "./shared/star.component";
import { PropertyDetailGuard } from "./property/property-guard.service";
import { PropertyDetailComponent } from "./property/property-detail.component";
import { WelcomeComponent } from "./home/welcome.component";
import { PropertyService } from "./property/property.service";
@NgModule({
imports: [
BrowserModule,
FormsModule,
HttpModule,
RouterModule.forRoot([
{ path: 'property', component: PropertyListComponent },
{ path: 'property/:id',
canActivate: [PropertyDetailGuard],
component: PropertyDetailComponent
},
{ path: 'welcome', component: WelcomeComponent },
{ path: '', redirectTo: 'welcome', pathMatch: 'full' },
{ path: '**', redirectTo: 'welcome', pathMatch: 'full' }
])
],
declarations: [
AppComponent,
PropertyListComponent,
PropertyCityFilterPipe,
StarComponent,
PropertyDetailComponent,
WelcomeComponent,
],
providers: [PropertyDetailGuard, PropertyService],
bootstrap: [ AppComponent ]
})
export class AppModule { }
property.service.ts
import { Injectable, } from "@angular/core";
//import { IProperty } from "./property";
import { Http, Response } from "@angular/http";
import { Observable } from "rxjs/Observable";
import "rxjs/add/operator/catch";
import "rxjs/add/operator/do";
import "rxjs/add/operator/map";
import { IProperty } from "./property";
@Injectable()
export class PropertyService {
private _propertyUrl = 'api/property/property.json';
constructor(private _http: Http) { }
getPropertys(): Observable<IProperty[]> {
return this._http.get(this._propertyUrl)
.map((response: Response) => <IProperty[]>response.json())
.do(data => console.log('All: ' + JSON.stringify(data)))
.catch(this.handleError);
}
getProperty(id: number): Observable<IProperty> {
return this.getPropertys()
.map((property: IProperty[]) => property.find(p => p.propertyId === id));
}
private handleError(error: Response) {
// in a real world app, we may send the server to some remote logging infrastructure
// instead of just logging it to the console
console.error(error);
return Observable.throw(error.json().error || 'Server error');
}
}
property-list.component.ts
import { Component, OnInit } from "@angular/core";
import { IProperty } from "./property";
import { PropertyService } from "./property.service";
@Component({
moduleId: module.id,
templateUrl: 'property-list.component.html',
styleUrls: ['property-list.component.css']
})
export class PropertyListComponent implements OnInit {
pageTitle: string = 'Rental Listings';
imageWidth: number = 120;
imageMargin: number = 2;
listFilter: string;
errorMessage: string;
property: IProperty[];
constructor(private _propertyService: PropertyService) {
}
ngOnInit(): void {
this._propertyService.getPropertys()
.subscribe(property => this.property = property,
error => this.errorMessage = <any>error);
}
onRatingClicked(message: string): void {
this.pageTitle = "Property: " + message;
}
}
property-detail.component.ts
import { Component, OnInit, OnDestroy } from "@angular/core";
import { ActivatedRoute, Router } from "@angular/router";
import { Subscription } from "rxjs/Subscription";
import { IProperty } from "./property";
import { PropertyService } from "./property.service";
@Component({
templateUrl: 'app/property/property-detail.component.html'
})
export class PropertyDetailComponent implements OnInit, OnDestroy {
pageTitle: string = 'Property Detail';
property: IProperty;
errorMessage: string;
private sub: Subscription;
constructor(private _route: ActivatedRoute,
private _router: Router,
private _propertyService: PropertyService) {
}
ngOnInit(): void {
this.sub = this._route.params.subscribe(
params => {
let id = +params['id'];
this.getProperty(id);
});
}
ngOnDestroy() {
this.sub.unsubscribe();
}
getProperty(id: number) {
this._propertyService.getProperty(id).subscribe(
property => this.property = property,
error => this.errorMessage = <any>error);
}
onBack(): void {
this._router.navigate(['/property']);
}
onRatingClicked(message: string): void {
this.pageTitle = 'Property Detail: ' + message;
}
}
property-detail.component.html(你会看到我只插入了一个指令 - {{property.propertyName}} 来简化事情
<div class='panel panel-primary'>
<div class='panel-heading' style='font-size:large'>
{{pageTitle}}
</div>
<div class='panel-body'>
<div class='row'>
<div class='col-md-6'>
<div class='row'>
<div class='col-md-3'>Name:</div>
<div class='col-md-6'>{{property.propertyName}}</div>
</div>
<div class='row'>
<div class='col-md-3'>Code:</div>
<div class='col-md-6'></div>
</div>
<div class='row'>
<div class='col-md-3'>Description:</div>
<div class='col-md-6'></div>
</div>
<div class='row'>
<div class='col-md-3'>Availability:</div>
<div class='col-md-6'></div>
</div>
<div class='row'>
<div class='col-md-3'>Price:</div>
<div class='col-md-6'></div>
</div>
<div class='row'>
<div class='col-md-3'>5 Star Rating:</div>
<div class='col-md-6'>
<!--<cx-star [rating]='property.starRating'
(ratingClicked)='onRatingClicked($event)'>
</cx-star>-->
</div>
</div>
</div>
<!--<div class='col-md-6'>
<img class='center-block img-responsive'
[style.width.px]='200'
[style.margin.px]='2'
[src]='property.imageUrl'
[title]='property.productName'>
</div>-->
</div>
</div>
<div class='panel-footer'>
<a class='btn btn-default' (click)='onBack()' style='width:80px'>
<i class='glyphicon glyphicon-chevron-left'></i> Back
</a>
</div>
</div>
我们将非常感谢您在这方面的任何帮助
【问题讨论】:
-
在顶部的div标签中添加指令*ngIf="property",它只会在属性收费时显示模板
-
我确实有这个,但由于该属性根本没有加载,所以我删除了它。
-
把 *ngIf="property" 放在标签{{property.propertyName}}else 在订阅者返回值之前和渲染模板property.propertyName 未定义
-
非常感谢,成功了!!!
标签: angular2-services angular2-directives