简体   繁体   English

Angular4 * ng如果不起作用/变量未定义

[英]Angular4 *ngIf not working / Variable is undefined

I am trying to get in my view details of a chosen item. 我正在尝试查看所选项目的详细信息。 It seems like the *ngIf statement doesn't work. * ngIf语句似乎不起作用。 It renders a plain page instead of "details" of a chosen "person". 它呈现一个普通页面,而不是所选“人物”的“详细信息”。 For testing purposes I exchanged the *ngIf statement into a true one *ngIf="1" , then I managed to get the page markup rendered (it worked!), but 为了进行测试,我将* ngIf语句交换为一个真正的*ngIf="1" ,然后设法呈现了页面标记(它起作用了!),但是

{{ person.name }} and `{{ person.id }}`

didn't work. 没用。 So, it looks like my details.html knows nothing about person variable. 因此,看起来我的details.htmlperson变量一无所知。

What should be done to get the details.html component rendered correctly? 为了正确显示details.html组件,应该怎么做?

person.service.ts person.service.ts

import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';

import { IPerson } from '../persons/person';

@Injectable()
export class PersonService {
  private _personUrl = './assets/persons.json';

  constructor(private _http:Http){}

  getPersons(): Observable<IPerson[]> {
    return this._http.get(this._personUrl)
    .map((response: Response) => <IPerson[]>response.json().personsData)
  }

   getPerson(id:number): Observable<IPerson>{
    return this.getPersons()
    .map(persons => persons.find(person => person.id === id));
  }

} }

details.component.html details.component.html

<div *ngIf="person" class="container">
  <h3>Person Details</h3>
  <div class="col-md-12">
     <div>{{ person.name }}</div>
     <div>{{ person.id }}</div>
  </div>

  <button (click)="goBack()">Back</button>
</div>

details.component.ts details.component.ts

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Params } from '@angular/router';
import { PersonService } from '../service/person.service';
import { IPerson } from '../persons/person';

@Component({
   selector: 'app-details',
   templateUrl: './details.component.html',
  styleUrls: ['./details.component.css'] 
})
export class DetailsComponent implements OnInit {
  public person: IPerson;

  constructor(
    private _PersonService: PersonService,
    private route: ActivatedRoute
    ) { }

  ngOnInit(): void {
    this.route.params.forEach((params: Params) => {
        let id = +params['id'];
        this._PersonService.getPerson(id)
    .map(person => this.person = person).subscribe();
    })
  }


}

persons.json persons.json

{
  "personsData" : [
    {
      "id": 1,
      "name": "KC"
    },
    {
      "id": 2,
      "name": "KN"
    },
    {
      "id": 3,
      "name": "DG"
    }]
 }

UPD It seems the problem is the person variable in details.component.ts which is undefined, although I declared it in the exported class. UPD似乎问题出在details.component.tsperson变量是未定义的,尽管我在导出的类中声明了它。

The params property of the ActivatedRoute returns an observable which you need to subscribe to. ActivatedRouteparams属性返回一个您需要订阅的Observable。 So we'd have to change your code to something like this: 因此,我们必须将您的代码更改为以下内容:

this.route.params.subscribe(...)

It's also advised to use paramsMap instead of params , which as its name describes will return a Map instead. 还建议使用paramsMap代替params ,正如其名称所描述的那样,它将返回Map。 So we can further change it to this: 因此,我们可以进一步将其更改为:

this.route.paramMap.subscribe(paramMap => paramMap.get('id'))

Now we're using the get method on a map, pass it the key, in this case the name of your param and in the end, this'll basically give us the same result. 现在,我们在地图上使用get方法,将键传递给它,在这种情况下,将其作为参数的名称,最后,这基本上会给我们相同的结果。

Another thing that is completely wrong with your code is the map operator. 您的代码完全错误的另一件事是map运算符。 When working with Observables, we use the map operator, to mutate the data emitted. 在使用Observables时,我们使用map运算符来对发出的数据进行突变。 So for instance, this observable is emitting a Person. 因此,例如,此可观察对象正在发出一个Person。 If you wanted just the person's name, you would use the map operator like this: 如果只需要此人的名字,则可以使用以下地图操作符:

.map(person => person.name)

And if you're not used to this syntax, then this is equivalent: 如果您不习惯这种语法,那么这是等效的:

.map(person => {return person.name})

The code that should run once you are receiving the desired data goes in the subscibe, which takes three arguments, but we usually only care about the first two, which are the success and error callback functions. 一旦接收到所需的数据,应运行的代码进入子例程中,该例程具有三个参数,但是我们通常只关心前两个参数,即成功和错误回调函数。 Your final code should look something like this: 您的最终代码应如下所示:

this.route.paramMap.subscribe(params => 
    this._PersonService.getPerson(+params.get('id'))
        .subscribe((person) => this.person = person, () => {  //do something on error}))

Your data is asynchronous so you have to use pipe async to render it: 您的数据是异步的,因此您必须使用管道异步来呈现它:

https://angular.io/api/common/AsyncPipe https://angular.io/api/common/AsyncPipe

Just add that pipe to interpolation and it will work. 只需将该管道添加到插值中,它将起作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM