如何修复“无法读取未定义的属性'标题'”

时间:2019-05-16 12:01:20

标签: angular typescript firebase

我正在关注Mosh Hamedani教程“ Angular 4:Pro的初学者”。

在尝试编辑产品时,我试图以表格形式显示产品标题。 产品存储在Firebase数据库中。 我是Angular的新手。

但是,当我进入编辑表单时,在控制台中出现此错误

ERROR TypeError: Cannot read property 'title' of undefined
    at Object.eval [as updateDirectives] (ProductFormComponent.html:7)
    at Object.debugUpdateDirectives [as updateDirectives] (core.js:23911)
    at checkAndUpdateView (core.js:23307)
    at callViewAction (core.js:23548)
    at execComponentViewsAction (core.js:23490)
    at checkAndUpdateView (core.js:23313)
    at callViewAction (core.js:23548)
    at execEmbeddedViewsAction (core.js:23511)
    at checkAndUpdateView (core.js:23308)
    at callViewAction (core.js:23548)

这是我表格的一部分:

<div class="form-group">
            <label for="title">Title</label>
            <input #title="ngModel" [(ngModel)]="product.title" <== error here
name="title" id="title" type="text" class="form-control" required>
            <div class="alert alert-danger" *ngIf="title.touched && title.invalid">
              Title is required
            </div>
          </div>

这是product-form.component.ts

import { Component, OnInit, OnDestroy } from '@angular/core';
import { CategoryService } from 'src/app/category.service';
import { ProductService } from 'src/app/product.service';
import { Router, ActivatedRoute } from '@angular/router';
import { take } from 'rxjs/operators';

@Component({
  selector: 'app-product-form',
  templateUrl: './product-form.component.html',
  styleUrls: ['./product-form.component.css']
})
export class ProductFormComponent implements OnInit {

  categories$;
  product;

  constructor(
    categoryService: CategoryService,
    private route: ActivatedRoute,
    private productService: ProductService,
    private router: Router) {
    this.categories$ = categoryService.getCategories();

    let id = this.route.snapshot.paramMap.get('id');
     if (id) this.productService.get(id).snapshotChanges().pipe(take(1))
.subscribe(p => this.product = p); <== this does not seem to be working
  }

  save(product) {
    this.productService.create(product);
    this.router.navigate(["/admin/products"]);
  }

  ngOnInit() {
  }

}

我该怎么做才能显示产品标题?

5 个答案:

答案 0 :(得分:0)

您也可以使用

product:any = {};

答案 1 :(得分:0)

更改

product;

product:any = {};

和(valueChanges()而不是snapshotChnages())

if (id) this.productService.get(id).snapshotChanges().pipe(take(1))
.subscribe(p => this.product = p); 
  }

if (id) this.productService.get(id).valueChanges().pipe(take(1))
.subscribe(p => this.product = p); <== this does not seem to be working
  }

已解决问题

答案 2 :(得分:0)

错误是因为启动时未初始化该值。 当变量从订阅中获取第一个值时会发生这种情况,这需要花费一些时间来获取值,因此视图会渲染并尝试在值存在之前获取它。 我建议先为您的数据创建一个模型,然后初始化您的模型 看一下Creating model classes in typescript关于如何创建模型的信息。 您可以在启动时将其初始化以避免错误,或者创建另一个变量以强制视图在该变量上等待。

import { Component, OnInit, OnDestroy } from '@angular/core';
import { CategoryService } from 'src/app/category.service';
import { ProductService } from 'src/app/product.service';
import { Router, ActivatedRoute } from '@angular/router';
import { take } from 'rxjs/operators';

@Component({
  selector: 'app-product-form',
  templateUrl: './product-form.component.html',
  styleUrls: ['./product-form.component.css']
})
export class ProductFormComponent implements OnInit {

  categories$;
  product;
initialized : boolean = false

  constructor(
    categoryService: CategoryService,
    private route: ActivatedRoute,
    private productService: ProductService,
    private router: Router) {
    this.categories$ = categoryService.getCategories();

    let id = this.route.snapshot.paramMap.get('id');
     if (id) this.productService.get(id).snapshotChanges().pipe(take(1))
.subscribe(p => {
this.initialized = true
this.product = p

});       }

  save(product) {
    this.productService.create(product);
    this.router.navigate(["/admin/products"]);
  }

  ngOnInit() {
  }

}

然后html看起来像这样:

<div class="form-group">
            <label for="title">Title</label>
            <input #title="ngModel" *ngIf="initialized" [(ngModel)]="product.title"
name="title" id="title" type="text" class="form-control" required>
            <div class="alert alert-danger" *ngIf="title.touched && title.invalid">
              Title is required
            </div>
          </div>

您可以使用该变量来创建自己喜欢的加载指示器

答案 3 :(得分:0)

您只需在外部容器上添加* ngIf =“ product”。仅当prodcut对象初始化时才会显示值。

答案 4 :(得分:0)

它有一个简单的解决方案。显示该错误的原因是,在初始化html组件时,产品尚未准备就绪(由于api调用需要一些时间才能返回数据),因此未定义。因此,请使用?.,如下所示html组件。



   <div class="form-group">
            <label for="title">Title</label>
            <input #title="ngModel" [(ngModel)]="product?.title" <== error here
name="title" id="title" type="text" class="form-control" required>
            <div class="alert alert-danger" *ngIf="title.touched && title.invalid">
              Title is required
            </div>
          </div>

    ````