【问题标题】:How to fix "Cannot read property 'title' of undefined"如何修复“无法读取未定义的属性‘标题’”
【发布时间】:2019-10-03 16:53:31
【问题描述】:

我正在关注 Mosh Hamedani 教程“Angular 4:初学者到专业人士”。

我在尝试编辑产品时尝试在表单中显示产品的标题。 该产品存储在 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() {
  }

}

如何显示产品的标题?

【问题讨论】:

  • 试试 product['title'] 而不是 product.title
  • @PareshGami 它与符号无关,似乎OP没有及时得到适当的响应!
  • 控制台“产品”并检查“标题”键是否可用

标签: angular typescript firebase


【解决方案1】:

它有一个简单的解决方案。显示错误是因为在初始化 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>

    ````

【讨论】:

    【解决方案2】:

    您可以简单地在外部容器上添加 *ngIf="product"。只有在 prodcut 对象初始化时才会显示值。

    【讨论】:

      【解决方案3】:

      该错误是因为该值在启动时未初始化。 当变量从订阅中获取其第一个值时会发生这种情况,这需要一些时间才能获取值,因此视图呈现并尝试在该值存在之前获取该值。 我建议首先为您的数据创建一个模型,然后初始化您的模型 查看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>
      

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

      【讨论】:

        【解决方案4】:

        变化

        product;
        

        product:any = {};
        

        and (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
          }
        

        已解决问题

        【讨论】:

          【解决方案5】:

          你也可以使用

          product:any = {};
          

          【讨论】:

          • 在哪里?为什么?请添加详细信息。
          • Hello Nino,您可以在其中定义 product 变量。只需替换为product:any = {};
          猜你喜欢
          • 2019-11-27
          • 2019-12-08
          • 2019-08-19
          • 2021-02-28
          • 2019-11-02
          • 2021-10-03
          • 2021-10-28
          • 2021-03-03
          • 1970-01-01
          相关资源
          最近更新 更多