Как исправить «Не удается прочитать свойство 'title' из undefined" - PullRequest
0 голосов
/ 16 мая 2019

Я следую учебному пособию Моша Хамедани "Angular 4: Beginner to 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>

А вот и товар-форма.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() {
  }

}

Что я могу сделать, чтобы показать название продукта?

Ответы [ 4 ]

0 голосов
/ 16 мая 2019

Вы можете просто добавить * ngIf = "product" во внешний контейнер. Значение будет отображаться только при инициализации объекта prodcut.

0 голосов
/ 16 мая 2019

Изменение

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
  }

исправили проблему

0 голосов
/ 16 мая 2019

Ошибка в том, что значение не инициализируется при запуске.Это происходит, когда переменная получает свое первое значение из подписки, что требует некоторого времени для получения значения, поэтому представление визуализируется и пытается получить значение до того, как оно существует.Я бы рекомендовал сначала создать модель для ваших данных, а затем инициализировать вашу модель. Посмотрите на Создание классов моделей в машинописи о том, как создать модель.Вы можете инициализировать его при запуске, чтобы избежать ошибки, или создать другую переменную, которая заставляет представление ждать переменную.

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>

Вы можете поиграться с переменной, чтобы создать индикатор загрузки по своему вкусу

0 голосов
/ 16 мая 2019

Вы также можете использовать

product:any = {};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...