Angular 2组件指令不与服务一起使用

时间:2017-06-08 14:37:38

标签: angular2-services angular2-directives

我是角度2的初学者,我正在建立我的第一个应用程序,同时遵循Pluralsight课程。 我正在使用TypeScript。 我有一个特定的组件(名为: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');
    }
}

属性-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;
    }


}

属性-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>

对此方面的任何帮助都将受到高度赞赏

1 个答案:

答案 0 :(得分:0)

把* ngIf =&#34;属性&#34;在标签{{property.propertyName}}内部,在订阅者返回值之前以及渲染时模板property.propertyName未定义 - alehn96 14小时前