0

在我的数据存储在 db 中后我遇到了一个问题,我想对其进行编辑。它没有显示数据,我收到无法读取属性错误。

html

admin-products.component.html

<p>
  <a routerLink="/admin/products/new" class="btn btn-primary">New Products</a>
</p>
<table class="table">
  <thead>
    <tr>
      <th>Title</th>
      <th>Price</th>
      <th></th>
    </tr>
  </thead>
  <tbody>
    <tr *ngFor="let p of products$ | async">
      <td>{{ p.title }}</td>
      <td>{{ p.price }}</td>
      <td><a [routerLink]="['/admin/products/', p.$key]">Edit</a></td>
    </tr>
  </tbody>
</table>

产品-form.component.html

如果我在控制台中检查错误链接,它会在所有输入字段中显示错误。我认为主要是错误可能在这里?

    <div class="row">
  <div class="col-md-6">
    <form #f="ngForm" (ngSubmit)="save(f.value)">
      <div class="form-group">
        <label for="title">Title</label>
        <input
          #title="ngModel"
          [(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>
      <div class="form-group">
        <label for="price">Price</label>
        <div class="input-group-prepend">
          <span class="input-group-text"> $ </span>
          <input
            #price="ngModel"
            [(ngModel)]="product.price"
            name="price"
            id="price"
            type="number"
            class="form-control"
            required
            [min]="0"
          />
        </div>
        <div class="alert alert-danger" *ngIf="price.touched && price.invalid">
          <div *ngIf="price.errors.required">Price is required.</div>
          <div *ngIf="price.errors.min">Price should be 0 or higher.</div>
        </div>
      </div>
      <div class="form-group">
        <label for="category">Category</label>
        <select
          #category="ngModel"
          [(ngModel)]="product.category"
          name="category"
          id="category"
          class="form-control"
          required
        >
          <option value=""></option>
          <option *ngFor="let c of categories$ | async" [value]="c.$key">
            {{ c.name }}
          </option>
        </select>
        <div
          class="alert alert-danger"
          *ngIf="category.touched && category.invalid"
        >
          Category is required
        </div>
      </div>
      <div class="form-group">
        <label for="imageUrl">Image Url</label>
        <input
          #imageUrl="ngModel"
          [(ngModel)]="product.imageUrl"
          name="imageUrl"
          id="imageUrl"
          type="text"
          class="form-control"
          required
          url
        />
        <div
          class="alert alert-danger"
          *ngIf="imageUrl.touched && imageUrl.invalid"
        >
          <div *ngIf="imageUrl.errors.required">Image is required</div>
          <div *ngIf="imageUrl.errors.url">Please enter a vaild URL</div>
        </div>
      </div>
      <button class="btn btn-primary">Save</button>
    </form>
  </div>
  <div class="col-md-6">
    <div class="card" style="width: 18rem;">
      <img
        class="card-img-top"
        [src]="product.imageUrl"
        *ngIf="product.imageUrl"
      />
      <div class="card-body">
        <h5 class="card-title">{{ product.title }}</h5>
        <p class="card-text">{{ product.price | currency: 'USD':true }}</p>
      </div>
    </div>
  </div>
</div>

产品-form.component.ts

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

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

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

    // tslint:disable-next-line:prefer-const
    let id = this.route.snapshot.paramMap.get('id');
    // tslint:disable-next-line:curly
    if (id)
      this.productService.get(id).valueChanges().take(1).subscribe(p => (this.product = p));
  }

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

产品服务.ts

import { Injectable } from '@angular/core';
import { AngularFireDatabase, AngularFireList } from 'angularfire2/database';
@Injectable()
export class ProductService {
  products$: AngularFireList<any[]>;
  constructor(private db: AngularFireDatabase) {
    this.products$ = this.db.list('/products');
  }
  create(product) {
    return this.products$.push(product);
  }

  getAll() {
    return this.db.list('/products').valueChanges();
  }

  get(productId) {
    return this.db.object('/products/' + productId);
  }
}

我已经使用 *ngIf , [ngModel]="product?.title" 尝试过这种方法

<input *ngIf="title">

4

2 回答 2

0

你试过用 ng-container 包装你的表单吗?

产品-form.component.ts

@Component({
  selector: 'app-product-form',
  templateUrl: './product-form.component.html',
  styleUrls: ['./product-form.component.css']
})
export class ProductFormComponent {
  categories$;
  product = null;

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

    // tslint:disable-next-line:prefer-const
    let id = this.route.snapshot.paramMap.get('id');
    // tslint:disable-next-line:curly
    if (id)
      this.productService.get(id).valueChanges().take(1).subscribe(p => (this.product = p));
  }

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

产品-form.component.html

<div class="row">
  <div class="col-md-6">
    <ng-container *ngIf="product">
       <form #f="ngForm" (ngSubmit)="save(f.value)">
       <!-- YOUR CODE -->
       </form>
    </ng-container>
  </div>
</div>
于 2019-09-16T21:37:41.717 回答
0

尝试这个,

export class ProductFormComponent {
  categories$;
  product = {
               "title": '',
               "price": '', 
               "category": '',
               "imageUrl": '',                
            };



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

        // tslint:disable-next-line:prefer-const
        let id = this.route.snapshot.paramMap.get('id');
        // tslint:disable-next-line:curly
        if (id)
          this.productService.get(id).valueChanges().take(1).subscribe(p => (this.product = p));
      }

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

它失败的原因是因为

this.productService.get(id).valueChanges().take(1).subscribe(p => (this.product = p));

上面这行代码需要一些时间才能从 firebase 获得响应,与此同时,HTML 组件将在此之前渲染,因此它正在尝试访问 HTML 组件中的产品对象,因为没有标题、价格、类别,和产品对象中的 imageUrl 会导致错误。所以分配空值,稍后在收到响应后更新

于 2019-09-17T06:01:18.487 回答